hdu3749Financial Crisis(点双连通分量)
题意:如果两个点不在一个连通图中,即无路径相连,输出"zero",如果在同一个连通图中,如果两点路径上必经过割点,输出"one",
其余输出"two or more",点双连通分量(第一次接触,之前都做得有向图缩点)
4/2日更:重新调整状态,重新做了一遍,总算理解并实现了代码。
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 10010; typedef long long ll; struct edge { int f,t, nxt; }e[maxn << 1]; int hd[maxn], tot; void add(int f, int t) { e[++tot] = { f,t,hd[f] }; hd[f] = tot; } int n, m, q; int low[maxn], dfn[maxn],lastcol[maxn],in[maxn],cnt,colnum; vector<int>col[maxn],incol[maxn]; stack<edge>S; int nowcol; void init() { memset(dfn, 0, sizeof(dfn)); memset(hd, 0, sizeof(hd)); memset(lastcol, 0, sizeof(lastcol)); memset(in, 0, sizeof(in)); cnt = colnum = nowcol = tot = 0; for (int i = 0; i < n; i++) { col[i].clear(); incol[i].clear(); } } void dfs(int u, int f) { low[u] = dfn[u] = ++cnt; in[u] = nowcol; for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (v == f)continue; if (!dfn[v]) { S.push(e[i]); dfs(v, u); low[u] = min(low[u], low[v]); if (low[v] >= dfn[u]) { edge tmp; colnum++; while (1) { tmp = S.top(); S.pop(); if (lastcol[tmp.f] != colnum) { //由于用的边来表示一个连通分量,一个点可能出现两次,比如1-2,2-3,2就出现了两次,所以需要判重处理, //但是这题数据比较水,不加也让A了 col[colnum].push_back(tmp.f);//记录这个点连通分量的节点 incol[tmp.f].push_back(colnum);//记录这个节点所在的点连通有那些 lastcol[tmp.f] = colnum; } if (lastcol[tmp.t] != colnum) { col[colnum].push_back(tmp.t); incol[tmp.t].push_back(colnum); lastcol[tmp.t] = colnum; } if (u == tmp.f && v == tmp.t)break; } } } else if (dfn[v] < dfn[u]) { S.push(e[i]); low[u] = min(low[u], dfn[v]); } } } int main() { //freopen("test.txt", "r", stdin); int cse = 1; while (scanf("%d%d%d", &n, &m, &q) && n) { init(); while (m--) { int a, b; scanf("%d%d", &a, &b); add(a, b); add(b, a); } for (int i = 0; i < n; i++) { if (!dfn[i]) { nowcol++; dfs(i, -1); } } printf("Case %d:\n", cse++); while (q--) { int a, b; scanf("%d%d", &a, &b); if (in[a] != in[b]) { printf("zero\n"); } else { int f = 0; for (int i = 0; i < incol[a].size()&&!f; i++) { for (int j = 0; j < incol[b].size(); j++) { //如果两点可以出现在同一点连通分量内且有两个以上的点 if(incol[a][i]==incol[b][j]&&col[incol[a][i]].size()>2){ f = 1; break; } } } if (f) { printf("two or more\n"); } else { printf("one\n"); } } } } return 0; }