【缩点+拓扑判链】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
");
87         else printf("No
");
88     }
89     return 0;
90 }
原文地址:https://www.cnblogs.com/xkui/p/4579131.html