大意:给定一些有向图间的关系问任意两点是不是可达的。
思路:Tarjan后直接看入度和出度为0的数量关系,如果大于1则肯定是不可能,相连通的。
#include<map> #include<queue> #include<cmath> #include<cstdio> #include<stack> #include<iostream> #include<cstring> #include<algorithm> #define LL int #define inf 0x3f3f3f3f #define eps 1e-8 #include<vector> #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 using namespace std; const int Ma = 10100; struct node{ int to,w,next; }q[Ma]; int head[Ma],dfn[Ma],num[Ma],du[Ma],stk[Ma],vis[Ma],low[Ma]; int cnt,top,tim,scc,out[Ma],in[Ma]; bool mp[1100][1100]; void Add(int a,int b){ q[cnt].to = b; q[cnt].next = head[a]; head[a] = cnt++; } void init(){ scc = cnt = top = 0; tim = 1; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(num,0,sizeof(num)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); memset(low,0,sizeof(low)); memset(mp,false,sizeof(mp)); } void Tarjan(int u){ low[u] = dfn[u] = tim++; vis[u] = 1; stk[top++] = u; for(int i = head[u]; ~i ; i = q[i].next){ int v = q[i].to; if(!vis[v]){ Tarjan(v); low[u] = min(low[u],low[v]); } else low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]){//找到极大联通分量 scc++; while(top > 0&&stk[top] != u){ top --; vis[stk[top] ] = 2; num[stk[top] ] = scc; } } } int main(){ int n,m,i,j,k,a,b,c,cla; scanf("%d",&cla); for(int zu = 1;zu <=cla;++ zu){ scanf("%d%d",&n,&m); init(); for(i = 0;i <m;++ i){ scanf("%d%d",&a,&b); Add(a,b); } for(i = 1;i <= n;++ i) if(!dfn[i]) Tarjan(i); bool bj = false; for(i = 1;i <= n;++ i){ for(j = head[i];~j; j = q[j].next){ int v = q[j].to; if(num[i] != num[v]){ out[num[i] ]++; in[num[v] ]++; } } } int ans1,ans2; ans1 = ans2 =0; for(i = 1;i <= scc;++ i){ if(in[i]==0) ans1++; if(out[i]==0) ans2++; cout<<i<<endl; } printf("Case %d: ",zu); if(ans1>1||ans2>1){ puts("The Burning Shadow consume us all"); } else{ puts("Kalimdor is just ahead"); } } return 0; }