Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=2874
【前言】
这两天在做LCA的问题。
昨天做了一道模板题,今天再做一道。
但是一开始就被C++WA而G++AC困惑着。
最后的最后,好久好久以后,终于得到了一个结论。
【思路】
题意所给是一个森林,那么加多一个虚根节点,使其成为一棵树。
如果两个节点的LCA是虚根节点,则表示不可连通。
否则距离等于每个节点到虚根节点的距离之和减去两倍LCA到虚根节点的距离。
可以使用并查集,但是貌似跟直接深搜的时间差不多。不过可能会好一点。
【代码】
#include <iostream> #include <vector> #include <cmath> using namespace std; const int maxn = 10000; struct node { int length; int index; int next; node(int idx = 0, int len = 0) { index = idx; length = len; } }edge[maxn<<1+5]; int head[maxn+5]; int ect; void addedge(int from, int to, int len) { edge[ect].index = to; edge[ect].length = len; edge[ect].next = head[from]; head[from] = ect; ect++; } int F[maxn<<1]; int B[maxn<<1]; int Pos[maxn+5]; int D[maxn+5]; int has[maxn+5]; void dfs(int rt, int level, int len, int &ct) { ct++; has[rt] = 1; F[ct] = rt; B[ct] = level; D[rt] = len; Pos[rt] = ct; int i; for (i=head[rt]; i+1!=0; i=edge[i].next) { if (has[edge[i].index]==0) { dfs(edge[i].index, level+1, len+edge[i].length, ct); ct++; F[ct] = rt; B[ct] = level; } } } int dpmin[maxn<<1+10][20]; void ST(int n) { int i,j; for (i=1; i<=n; i++) { dpmin[i][0] = i; } int m = (int)floor(log((double)n)/log(2.0)); for (j=1; j<=m; j++) { for (i=1; i<=n; i++) { dpmin[i][j] = dpmin[i][j-1]; if (i+(1<<(j-1))<=n) { if (B[dpmin[i][j-1]]<B[dpmin[i+(1<<(j-1))][j-1]]) dpmin[i][j] = dpmin[i][j-1]; else dpmin[i][j] = dpmin[i+(1<<(j-1))][j-1]; } } } } int st_getmin(int l, int r) { int k = floor(log((double)(r-l+1))/log(2.0)); if (B[dpmin[l][k]]<B[dpmin[r-(1<<k)+1][k]]) return dpmin[l][k]; else return dpmin[r-(1<<k)+1][k]; } int getmin(int a, int b) { a = Pos[a], b = Pos[b]; if (a>b) swap(a, b); return F[st_getmin(a, b)]; } void solve(int rt) { int ct = 0; memset(has, 0, sizeof(has)); dfs(rt, 0, 0, ct); ST(ct); } int father[maxn+5]; void init(int n) { int i; for (i=0; i<=n; i++) { father[i] = i; } } inline int getroot(int x) { int r = x; while(father[r]!=r) { r = father[r]; } while(father[x]!=r) { father[x] = r; x = father[x]; } return r; } inline void join(int s, int x) { int a = getroot(s); int b = getroot(x); if (a!=b) { father[a] = b; } } int main() { int n, m, c; int x, y, z; int i; while(scanf("%d %d %d", &n, &m, &c)!=EOF) { for (i=1; i<=n+1; i++) head[i] = -1; ect = 0; //以下所有注释部分就是使用并查集 // init(n+1); for (i=0; i<m; i++) { scanf("%d %d %d", &x, &y, &z); addedge(x, y, z); addedge(y, x, z); // join(x, y); } memset(has, 0, sizeof(has));//这部分是使用深搜 for (i=1; i<=n; i++) { if (has[i]==0) { addedge(n+1, i, 0); z = 0;//如果不赋值为0,g++AC,c++WA。 dfs(i, 0, 0, z); } } /* for (i=1; i<=n; i++) if (father[i]==i) addedge(n+1, i, 0);*/ solve(n+1); while(c--) { scanf("%d %d", &x, &y); int rt = getmin(x, y); if (rt==n+1) printf("Not connected\n"); else printf("%d\n", D[x]+D[y]-2*D[rt]); } } return 0; }