题意:
给出一个图和一系列查询,查询是给出两个点,问两点之间有多少条点不重复的路径
要点:
明显是点双连通,如果u,v不连通(并查集处理)输出0;如果u,v处于同一个点双连通分量,输出2(注意这里如果这个分量只有两个点一条边输出1);如果不同,输出1即可。
注意这题有个地方要处理,我们知道割顶可以是好几个点双连通分量的公共点,所以如果直接用白书上的bccno数组来判断割顶处于哪个点双连通分量,它只会显示一个,这里就会出错,所以用一个belong数组把所有能出现的位置都记录下来。
#include#include #include #include #include using namespace std;const int maxn = 5050;int pre[maxn], bccno[maxn], dfs_clock, bcc_cnt;//bccno是判断当前点是否已经入块int pa[maxn];typedef pair Pair;vector g[maxn], bcc[maxn];//bcc是存放每个块中有的点stack s;//栈存放当前块中的边vector belong[maxn];int dfs(int u, int fa){ int lowu = pre[u] = ++dfs_clock; int child = 0; for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; Pair e = make_pair(u, v); if (!pre[v]) { s.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if (lowv >= pre[u]) { bcc_cnt++; bcc[bcc_cnt].clear(); while (1)//将当前栈中的边存储 { Pair x = s.top(); s.pop(); if (bccno[x.first] != bcc_cnt) { bcc[bcc_cnt].push_back(x.first); bccno[x.first] = bcc_cnt; belong[x.first].push_back(bcc_cnt);//将割顶放入所有的双连通分量 } if (bccno[x.second] != bcc_cnt) { bcc[bcc_cnt].push_back(x.second); bccno[x.second] = bcc_cnt; belong[x.second].push_back(bcc_cnt); } if (x.first == u&&x.second == v) break; } } } else if (pre[v] < pre[u] && v != fa)//已经访问过就更新low { s.push(e); lowu = min(lowu, pre[v]); } } return lowu;}void find_bcc(int n){ memset(pre, 0, sizeof(pre)); memset(bccno, 0, sizeof(bccno)); while (!s.empty()) s.pop(); dfs_clock = bcc_cnt = 0; for (int i = 1; i <= n; i++) if (!pre[i]) dfs(i, -1);}int find(int i){ return pa[i] == -1 ? i : pa[i]=find(pa[i]);}void init(){ for (int i = 0; i < maxn; i++) { g[i].clear(); bcc[i].clear(); belong[i].clear(); } memset(pa, -1, sizeof(pa));}int main(){ int n, m, q ,kase=1; int x, y,u,v; while (scanf("%d%d%d", &n, &m, &q)) { if (!n && !m && !q) break; init(); for (int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); x++, y++; g[x].push_back(y); g[y].push_back(x); u = find(x); v = find(y); if (u != v) pa[u] = v; } find_bcc(n); printf("Case %d:\n", kase++); while (q--) { int u, v; scanf("%d%d", &u, &v); u++, v++; if (find(u) != find(v)) printf("zero\n"); else { bool flag = false; for (int i = 0; i 2) printf("two or more\n"), flag = true; } } if (!flag) printf("one\n"); } } } return 0;}