POJ2762 Going from u to v or from v to u? 强连通分量缩点+拓扑排序
Posted yuanweidao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ2762 Going from u to v or from v to u? 强连通分量缩点+拓扑排序相关的知识,希望对你有一定的参考价值。
题目链接:https://vjudge.net/contest/295959#problem/I 或者 http://poj.org/problem?id=2762
题意:输入多组样例,输入n个点和m条有向边,问该图中任意两点x, y之间是否满足x可以到y或者y可以到x。
一开始WA的原因是因为没注意到是或者, 如果是并且的话,就是一道简单的强连通分量的题,直接判断整个图是否为一个强连通分量
对于该题, 先用强连通分量进行缩点,简化图。图就变成了DAG,用拓扑排序判断图中点的入度, 图中入度为0的点只能存在一个, 若存在2个及以上的话,那么这2个点或多个点是无法互相到达。
在拓扑排序中用列队, 入度为0的点入队,每次都对列队中的数判断,若大于等于2则直接return 不满足。
#include<stdio.h> #include<string.h> #include<stack> #include<queue> #include<algorithm> using namespace std; int n, m, cnt, cnt1; int head[1010], head1[1010]; int dfn[1010], low[1010], vis[1010], deep, k_color, color[1010]; stack<int>S; int in[1010], flag; struct Edge { int to, next; }edge[6010], edge1[6010]; void add(int a, int b) { edge[++ cnt].to = b; edge[cnt].next = head[a]; head[a] = cnt; } void add1(int a, int b) { edge[++ cnt1].to = b; edge[cnt1].next = head1[a]; head1[a] = cnt1; } void tarjan(int now) { dfn[now] = low[now] = ++ deep; vis[now] = 1; S.push(now); for(int i = head[now]; i != -1; i = edge[i].next) { int to = edge[i].to; if(!dfn[to]) { tarjan(to); low[now] = min(low[now], low[to]); } else if(vis[to]) { low[now] = min(low[now], dfn[to]); } } if(dfn[now] == low[now]) { k_color ++; while(1) { int temp = S.top(); S.pop(); color[temp] = k_color; vis[temp] = 0; if(temp == now) break; } } } void topo_sort() { queue<int>Q; while(!Q.empty()) Q.pop(); for(int i = 1; i <= k_color; i ++) if(!in[i]) Q.push(i); if(Q.size() > 1) { flag = 0; return ; } while(!Q.empty()) { int temp = Q.front(); Q.pop(); for(int i = head1[temp]; i != -1; i = edge[i].next) { int to = edge[i].to; in[to] --; if(!in[to]) Q.push(to); if(Q.size() > 1) { flag = 0; return ; } } } } int main() { int T; scanf("%d", &T); while(T --) { flag = 1; cnt = deep = k_color = cnt1 = 0; memset(head, -1, sizeof(head)); memset(in, 0, sizeof(in)); memset(head1, -1, sizeof(head1)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(vis, 0, sizeof(vis)); scanf("%d%d", &n, &m); for(int i = 1; i <= m; i ++) { int a, b; scanf("%d%d", &a, &b); add(a, b); } for(int i = 1; i <= n; i ++) if(!dfn[i]) tarjan(i); for(int i = 1; i <= n; i ++)//缩点 { for(int j = head[i]; j != -1; j = edge[j].next) { int to = edge[j].to; int x = color[i], y = color[to]; if(x != y) { add1(x, y); in[y] ++; } } } topo_sort(); if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }
以上是关于POJ2762 Going from u to v or from v to u? 强连通分量缩点+拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2762 Going from u to v or from v to u? (判断弱连通)
[POJ2762]Going from u to v or from v to u?
POJ2762 Going from u to v or from v to u? 强连通+缩点
POJ2762 Going from u to v or from v to u? 强连通分量缩点+拓扑排序
POJ - 2762 Going from u to v or from v to u? (强连通缩点+判断单向连通)
POJ 2762--Going from u to v or from v to u?scc缩点新建图 && 推断是否是弱连通图