【缩点+拓扑判链】POJ2762 Going from u to v or from v to u?
Description
In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
Solution
缩点,满足题意的充要条件是存在一条完整的链,这个可以用“是否存在唯一拓扑序”解决。
Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int maxn=1e5+5; 6 7 int pre[maxn],low[maxn],clock; 8 int scc[maxn],s[maxn],c,cnt; 9 int head[maxn],e[maxn],nxt[maxn],k; 10 void adde(int u,int v){ 11 e[++k]=v;nxt[k]=head[u];head[u]=k; 12 } 13 int _head[maxn],_e[maxn],_nxt[maxn],_k; 14 void _adde(int u,int v){ 15 _e[++_k]=v;_nxt[_k]=_head[u];_head[u]=_k; 16 } 17 int n,m; 18 19 int r[maxn],vis[maxn]; 20 int topo(){ 21 for(int i=1;i<=cnt;i++){ 22 int tot=0,u; 23 for(int i=1;i<=cnt;i++)//偷懒 24 if(!r[i]&&!vis[i]) tot++,u=i; 25 if(tot>1) return 0; 26 vis[u]=1; 27 for(int i=_head[u];i;i=_nxt[i]) 28 r[_e[i]]--; 29 } 30 return 1; 31 } 32 33 void dfs(int u){ 34 pre[u]=low[u]=++clock; 35 s[++c]=u; 36 for(int i=head[u];i;i=nxt[i]){ 37 int v=e[i]; 38 if(!pre[v]){ 39 dfs(v); 40 low[u]=min(low[u],low[v]); 41 } 42 else if(!scc[v]){ 43 low[u]=min(low[u],pre[v]); 44 } 45 } 46 if(low[u]==pre[u]){ 47 cnt++; 48 while(c){ 49 scc[s[c]]=cnt; 50 if(s[c--]==u) break; 51 } 52 } 53 } 54 55 void clear(){ 56 memset(head,0,sizeof(head)); 57 memset(_head,0,sizeof(_head)); 58 memset(pre,0,sizeof(pre)); 59 memset(low,0,sizeof(low)); 60 memset(vis,0,sizeof(vis)); 61 memset(r,0,sizeof(r)); 62 c=cnt=k=_k=0; 63 } 64 65 int main(){ 66 int T; 67 scanf("%d",&T); 68 while(T--){ 69 clear(); 70 scanf("%d%d",&n,&m); 71 for(int i=1;i<=m;i++){ 72 int u,v; 73 scanf("%d%d",&u,&v); 74 adde(u,v); 75 } 76 for(int i=1;i<=n;i++) 77 if(!pre[i]) dfs(i); 78 79 for(int i=1;i<=n;i++) 80 for(int j=head[i];j;j=nxt[j]){ 81 int u=scc[i],v=scc[e[j]]; 82 if(u==v) continue; 83 else _adde(u,v),r[v]++; 84 } 85 86 if(topo()) printf("Yes\n"); 87 else printf("No\n"); 88 } 89 return 0; 90 }