标签:
时间限制:1秒 内存限制:128兆
2 6 a to tea ted ten inn 4 sa sb sc sd
Case #1: 13 Case #2: 5 ///////////////////////////////////// For the second case, if the root has only one child, it’s a special leaf and must be calculate.
/** 题意:给几个字符串,构成一个字典树,求哪个节点到每个叶子的距离最短的,最短是多少 做法:先建立一个字典树,然后求公共祖先(求得是所有点到叶子节点的最短的距离) **/ #include <iostream> #include <algorithm> #include <cmath> #include <stdio.h> #include <string.h> #include <queue> using namespace std; #define maxn 100010 int tot = 0 ; const int MAXN = 100010; const int DEG = 30; int num[maxn]; int tot2 = 0; int tot3 = 0; int num1[maxn]; int indegree[maxn]; int mmap[maxn]; int mm = 0; struct Node { int x; int y; int flag; Node() {}; Node(int _x, int _y) { x = _x; y = _y; flag = 0; } } node[maxn << 1]; struct Trie { int next[maxn][30], end[maxn]; int root; int L; int newnode() { for(int i = 0; i < 26; i++) { next[L][i] = -1; } end[L++] = 0; return L - 1; } void init() { L = 0; root = newnode(); } void insert(char buf[]) { int len = strlen(buf); int now = root; for(int i = 0; i < len; i++) { if(next[now][buf[i] - ‘a‘] == -1) { next[now][buf[i] - ‘a‘] = newnode(); node[tot].y = next[now][buf[i] - ‘a‘] + 1; node[tot].x = now + 1; node[tot].flag = 0; tot++; } now = next[now][buf[i] - ‘a‘]; } node[tot - 1].flag = 1; num[tot2++] = node[tot - 1].y; end[now]++; } }; Trie ac; struct Edge { int to; int next; } edge[MAXN * 2]; int head[MAXN], tot1; void addedge(int u, int v) { edge[tot1].to = v; edge[tot1].next = head[u]; head[u] = tot1++; } void init() { tot1 = 0; memset(head, -1, sizeof(head)); } int fa[MAXN << 1][DEG]; int deg[MAXN << 1]; void bfs(int root) { queue<int>que; deg[root] = 0; fa[root][0] = root; que.push(root); while(!que.empty()) { int tmp = que.front(); que.pop(); for(int i = 1; i < DEG; i++) { fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1]; } for(int i = head[tmp]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == fa[tmp][0]) { continue; } deg[v] = deg[tmp] + 1; fa[v][0] = tmp; que.push(v); } } } int LCA(int u, int v) { if(deg[u] > deg[v]) { swap(u, v); } int hu = deg[u], hv = deg[v]; int tu = u, tv = v; for(int det = hv - hu, i = 0; det; det >>= 1, i++) if(det & 1) { tv = fa[tv][i]; } if(tu == tv) { return tu; } for(int i = DEG - 1; i >= 0; i--) { if(fa[tu][i] == fa[tv][i]) { continue; } tu = fa[tu][i]; tv = fa[tv][i]; } return fa[tu][0]; } bool flag[MAXN]; char buf[30]; int main() { //freopen("in.txt", "r", stdin); int Case = 1; int T; scanf("%d", &T); while(T--) { int n; tot = 1; ///边的数目 tot2 = 0; ///叶子节点的数目 如果根节点存在Case 2 中的情况也加进去 tot3 = 0; ///不是叶子的节点的节点 mm = 0; memset(node, 0, sizeof(node)); memset(indegree, 0, sizeof(indegree)); memset(flag, 0, sizeof(flag)); scanf("%d", &n); ac.init(); for(int i = 0; i < n; i++) { scanf("%s", buf); ac.insert(buf); } init(); int yy = 0; for(int i = 1; i < tot; i++) { addedge(node[i].x, node[i].y); addedge(node[i].y, node[i].x); indegree[node[i].x] ++; indegree[node[i].y] ++; yy = max(yy, max(node[i].x, node[i].y)); } for(int i = 1; i < tot; i++) { if(indegree[node[i].x] == 1) { mmap[mm++] = node[i].x; } else { num1[tot3++] = node[i].x; } if(indegree[node[i].y] == 1) { mmap[mm++] = node[i].y; } else { num1[tot3++] = node[i].y; } } sort(mmap, mmap + mm); sort(num1, num1 + tot3); int newmm = unique(mmap, mmap + mm) - mmap; int newtot3 = unique(num1, num1 + tot3) - num1; bfs(1); int mmin = 0xfffffff; for(int i = 1; i <= yy; i++) { int temp = 0; for(int j = 0; j < newmm; j++) { if(i != mmap[j]) { int tt = LCA(i, mmap[j]); int res = 0; res = abs(deg[i] - deg[tt]) + abs(deg[mmap[j]] - deg[tt]); temp += res; } } mmin = min(mmin, temp); } printf("Case #%d: %d\n", Case++, mmin); } return 0; }
标签:
原文地址:http://www.cnblogs.com/chenyang920/p/4786256.html