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

给出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 }

时间: 2024-10-11 13:39:00

poj 2762 Going from u to v or from v to u? 【 强连通 拓扑排序】的相关文章

POJ 2762 Going from u to v or from v to u?(强连通分量+拓扑排序)

职务地址:id=2762">POJ 2762 先缩小点.进而推断网络拓扑结构是否每个号码1(排序我是想不出来这点的. .. ).由于假如有一层为2的话,那么从此之后这两个岔路的点就不可能从一点到还有一点的. 代码例如以下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include

POJ 2762 Going from u to v or from v to u? (有向图求单连通性)

POJ 2762 Going from u to v or from v to u? 链接:http://poj.org/problem?id=2762 题意:为了让他们的儿子变得更勇敢些,Jiajia 和Wind 将他们带到一个大洞穴中.洞穴中有n 个房间,有一些单向的通道连接某些房间.每次,Wind 选择两个房间x 和y,要求他们的一个儿子从一个房间走到另一个房间,这个儿子可以从x 走到y,也可以从y 走到x.Wind 保证她布置的任务是可以完成的,但她确实不知道如何判断一个任务是否可以完成

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<algorit

[ tarjan + dfs ] poj 2762 Going from u to v or from v to u?

题目链接: http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14546   Accepted: 3837 Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cav

poj 2762 Going from u to v or from v to u? (判断是否是弱联通图)

题意:给定一个有向图有m条单向边,判断是否任意两点都可达(a能到b或者b能到a或者互相可达),即求 弱联通分量. 算法: 先缩点求强连通分量.然后重新建图,判断新图是否是一条单链,即不能分叉,如果分叉了就会存在不可达的情况. 怎么判断是否是单链呢? 就是每次入度为0的点都只有一个,即每次队列里只有一个点. (    o(╯□╰)o.....好像已经是第二次用pair记录原图的点对,然后存pair的vector忘记清空导致wa来wa去! ) #include<cstdio> #include&l

POJ 2762 Going from u to v or from v to u?(强联通,拓扑排序)

http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14573   Accepted: 3849 Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has

POJ 2762 Going from u to v or from v to u? (图论-tarjan)

Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14469   Accepted: 3801 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

poj 2762 Going from u to v or from v to u?

Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17689   Accepted: 4745 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,

[强连通分量] POJ 2762 Going from u to v or from v to u?

Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17089   Accepted: 4590 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