Financial Crisis
题意:给一个图,包含N ( 3 <= N <= 5000 )个点, M ( 0 <= M <= 10000 )条边 and Q ( 1 <= Q <= 1000 )次查询.查询:两个点是否是点-双连通;
点-双连通:两点至少存在两条"点不重复"的路径;简称双连通(biconnected);
思路:直接调用dfs求割点的算法,其实也是Tarjan发明的,就是在判断出一个割点之后,就把栈S中该双连通分量的所有点(就在栈顶)insert到同一个集合中;
注意:一个点可以属于多个双连通分类,所以bccno数组其实只是一个防止重复insert同一个点,在set中可以除去。并且注意初始化各种数组即序号(这样都TLE几次)
PS:原本使用链式向前星来存储边,可是发现在hd里竟然比直接vector建图还慢。。(一脸茫然);并且开始使用stack<PII> 直接MLE了,可是看别人直接使用库栈。。
#include<iostream> #include<sstream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) const int MAXN = 10010; int low[MAXN],pre[MAXN],dfs_clock,bcc_cnt; int bccno[MAXN];//看点属于哪个双连通分量; set<int> bcc[MAXN];//存储每一个双连通分量的点的标号; typedef pair<int,int> PII; #define A first #define B second #define pb push_back PII S[MAXN<<1];//存储边,从中取点 vector<int> e[MAXN]; int top; int dfs(int u,int fa) { int lowu = pre[u] = ++dfs_clock; int child = 0; rep0(i,0,e[u].size()){ int v = e[u][i]; PII e = PII{u,v}; if(!pre[v]){ S[++top] = e; child++; int lowv = dfs(v,u); lowu = min(lowu,lowv);//以子节点的low来更新u的low函数; if(lowv >= pre[u]){ //表示u-v为桥 bcc[++bcc_cnt].clear(); for(;;){ PII x = S[top--]; if(bccno[x.A] != bcc_cnt){bcc[bcc_cnt].insert(x.A);bccno[x.A] = bcc_cnt;}//就是为了不重复加点 if(bccno[x.B] != bcc_cnt){bcc[bcc_cnt].insert(x.B);bccno[x.B] = bcc_cnt;} if(x.A == u && x.B == v) break;//根据加入的顺序知,正好对应; } } } else if(v != fa && pre[v] < pre[u]){ S[++top] = e; lowu = min(lowu,pre[v]); } } return low[u] = lowu; } int f[MAXN]; int Find(int a) { return a==f[a]?f[a]:f[a]=Find(f[a]); } char ans[][15] = {"zero","one","two or more"}; int main() { int N,M,Q,kase = 1; while(scanf("%d%d%d",&N,&M,&Q) == 3 && N+M+Q){ rep0(i,0,N){ f[i] = i; e[i].clear();//直接vector建图 } int u,v; rep0(i,0,M){ scanf("%d%d",&u,&v); e[u].pb(v);e[v].pb(u); u = Find(u),v = Find(v); if(u != v) f[v] = u; } bcc_cnt = dfs_clock = top = 0; MS0(pre);MS0(bccno); rep0(i,0,N)if(pre[i] == 0) dfs(i,-1); printf("Case %d:\n",kase++); rep0(i,0,Q){ int ret; scanf("%d%d",&u,&v); if(Find(u) != Find(v)) ret = 0; else{ ret = 1; rep1(j,1,bcc_cnt){ if(bcc[j].find(u) != bcc[j].end() && bcc[j].find(v) != bcc[j].end()&&bcc[j].size() > 2) ret = 2; } } printf("%s\n",ans[ret]); } } return 0; }
时间: 2024-12-26 20:04:15