码迷,mamicode.com
首页 > 编程语言 > 详细

poj 2762 Going from u to v or from v to u? 【 强连通 拓扑排序】

时间:2015-08-03 16:33:41      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:

给出n个点,m条边,问是否任意两点u,v,是否满足u能够到达v,或者v能够到达u

自己写的时候以为缩一下点,然后再判断一下能不能拓扑排序就可以了

但是--wa---

后来看了这篇题解

http://edward-mj.com/archives/27

技术分享

按紫书上讲的,如果图中存在有向环,则不存在拓扑排序,反之则存在

所以上面这幅图是满足拓扑排序的

但是因为u,v的入度都为0,u,v之间不能到达

所以缩点完之后的图应该满足是一条长链才行

技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<stack>
  6 #include<queue>
  7 #include<vector>
  8 using namespace std;
  9 
 10 const int maxn = 20005;
 11 int first[maxn];
 12 int low[maxn],pre[maxn],sc[maxn];
 13 int in[maxn],dout[maxn];
 14 int n,m;
 15 int ecnt,scnt,dfs_clock;
 16 stack<int> S;
 17 
 18 vector<int> g[maxn];
 19 int c[maxn];
 20 int ans[maxn];
 21 
 22 struct Edge{
 23     int v,next;
 24 }e[3*maxn];
 25 
 26 void init(){
 27     ecnt = 0;
 28     memset(first,-1,sizeof(first));
 29     memset(in,0,sizeof(in));
 30     memset(dout,0,sizeof(dout));
 31 }
 32 
 33 void addedges(int u,int v){
 34     e[ecnt].v = v;
 35     e[ecnt].next = first[u];
 36     first[u] = ecnt++;
 37 }
 38 
 39 void dfs(int u){
 40     low[u] = pre[u] = ++dfs_clock;
 41     S.push(u);
 42     for(int i = first[u];~i;i = e[i].next){
 43         int v = e[i].v;
 44         if(!pre[v]){
 45             dfs(v);
 46             low[u] = min(low[u],low[v]);
 47         }
 48         else if(!sc[v]) low[u] = min(low[u],pre[v]);
 49     }
 50     if(pre[u] == low[u]){
 51         scnt++;
 52         for(;;){
 53             int x = S.top();S.pop();
 54             sc[x] = scnt;
 55             if(x == u) break;
 56         }
 57     }
 58 }
 59 
 60 void find_scc(){
 61     while(!S.empty()) S.pop();
 62     memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
 63     memset(sc,0,sizeof(sc));
 64     dfs_clock = scnt = 0;
 65     for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
 66 }
 67 
 68 bool topsort(int N) {
 69     queue<int> s;
 70     for (int i = 1; i <= N; i++) {
 71         if (!in[i]) s.push(i);
 72         if (s.size() == 2) return false;
 73     }
 74     while (!s.empty()) {
 75         int u = s.front();s.pop();
 76         bool flag = false;
 77         for (int i = 0; i < g[u].size(); i++) {
 78             int v = g[u][i];
 79             in[v] -= 1;
 80             if (!in[v]) {
 81                 if (flag) return false;
 82                 s.push(v);
 83                 flag = true;
 84             }
 85         }
 86     }
 87     return true;
 88 }
 89 
 90 
 91 int main(){
 92     int T;
 93     scanf("%d",&T);
 94     while(T--){
 95         scanf("%d %d",&n,&m);
 96         init();
 97         for(int i = 1;i <= m;i++){
 98             int u,v;
 99             scanf("%d %d",&u,&v);
100             addedges(u,v);
101         }
102         find_scc();
103         if(scnt == 1) {
104             puts("Yes");
105             continue;
106         }
107         for(int i = 1;i <= scnt;i++) g[i].clear();
108         for(int u = 1;u <= n;u++){
109             for(int i = first[u];~i;i = e[i].next){
110                 int v = e[i].v;
111                 if(sc[u] != sc[v]) {
112                     g[sc[u]].push_back(sc[v]);
113                     in[sc[v]]++;
114                 }
115             }
116         }
117         if(topsort(scnt)) puts("Yes");
118         else puts("No");
119     }
120     return 0;
121 }
View Code

 

poj 2762 Going from u to v or from v to u? 【 强连通 拓扑排序】

标签:

原文地址:http://www.cnblogs.com/wuyuewoniu/p/4699222.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!