POJ 2762 Going from u to v or from v to u? (判断单连通)
http://poj.org/problem?id=2762
题意:
给出有向图,判断任意两个点u和v,是否可以从u到v或者从v到u。
思路:
判断图是否是单连通的。
首先来一遍强连通缩点,重新建立新图,接下来我们在新图中找入度为0的点,入度为0的点只能有1个,如果有多个那么这些个点肯定是不能相互到达的。
如果只有一个入度为0的点,走一遍dfs判断新图是否是单链,如果有分支,那么分支上的点肯定是不能相互到达的。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 using namespace std; 11 typedef long long LL; 12 13 const int maxn=6000+5; 14 15 int n,m; 16 17 int x[maxn],y[maxn]; 18 int in[maxn]; 19 int flag; 20 21 vector<int> G[maxn]; 22 vector<int> new_G[maxn]; 23 24 stack<int> S; 25 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; 26 27 void dfs(int u) 28 { 29 pre[u] = lowlink[u] = ++dfs_clock; 30 S.push(u); 31 for (int i = 0; i < G[u].size(); i++) 32 { 33 int v = G[u][i]; 34 if (!pre[v]) 35 { 36 dfs(v); 37 lowlink[u] = min(lowlink[u], lowlink[v]); 38 } 39 else if(!sccno[v]) 40 lowlink[u] = min(lowlink[u], pre[v]); 41 } 42 if (pre[u] == lowlink[u]) 43 { 44 scc_cnt++; 45 for(;;) 46 { 47 int x = S.top(); S.pop(); 48 sccno[x] = scc_cnt; 49 if (x == u) break; 50 } 51 } 52 } 53 54 void find_scc(int n) 55 { 56 dfs_clock = scc_cnt = 0; 57 memset(pre, 0, sizeof(pre)); 58 memset(sccno, 0, sizeof(sccno)); 59 for (int i = 1; i <= n; i++) 60 if (!pre[i]) dfs(i); 61 } 62 63 64 void dfs2(int u) 65 { 66 if(flag==0) return; 67 if(new_G[u].size()>1) {flag=0;return;} 68 if(new_G[u].size()!=0) dfs2(new_G[u][0]); 69 } 70 71 72 void rebulid() 73 { 74 for(int i=1;i<=scc_cnt;i++) {new_G[i].clear();in[i]=0;} 75 for(int i=0;i<m;i++) 76 { 77 if(sccno[x[i]]!=sccno[y[i]]) 78 { 79 new_G[sccno[x[i]]].push_back(sccno[y[i]]); 80 in[sccno[y[i]]]=1; 81 } 82 } 83 int num=0; 84 int pos; 85 for(int i=1;i<=scc_cnt;i++) 86 { 87 if(in[i]==0) {num++;pos=i;} 88 if(num>=2) {flag=0;return;} 89 } 90 if(flag) dfs2(pos); 91 } 92 93 int main() 94 { 95 //freopen("D:\\input.txt","r",stdin); 96 int T; 97 scanf("%d",&T); 98 while(T--) 99 { 100 flag=1; 101 scanf("%d%d",&n,&m); 102 for(int i=1;i<=n;i++) G[i].clear(); 103 for(int i=0;i<m;i++) 104 { 105 scanf("%d%d",&x[i],&y[i]); 106 G[x[i]].push_back(y[i]); 107 } 108 find_scc(n); 109 rebulid(); 110 if(flag) puts("Yes"); 111 else puts("No"); 112 } 113 return 0; 114 }