POJ 2762 证明是否为单向连通图 强连通缩点+类拓扑排序

来源:互联网 发布:如何检测网络丢包 编辑:程序博客网 时间:2024/05/17 08:48

题意:

测试数据数

给定n个点 m条有向边

问:是否对于图中任意两点 u,v 都满足 u到v 或v到u  (就是单连通图的定义)

思路:

求证单连通图

我们先把有向图缩点为缩点树 (强连通缩点)

再进行类似于拓扑排序的操作:

则我们先选一个入度为0的点入队(一定是入度为0 的点为起点 ,注意只能选一个点

我们对于任意点u,让u点走到一个未走过的点 v (注意每个点只能转移到一个点

这样使得所有的点都被经过 则满足单连通图

以上的类拓扑排序是个人YY的结论,没有详细的证明。

 

 

#include<stdio.h>#include<string.h>#include<iostream>#include<vector>#include<queue>using namespace std;#define N 1010//N为点数#define M 6005//M为边数int n, m;struct Edge{int from, to, nex;bool sign;//是否为桥}edge[M<<1];int head[N], edgenum;void add(int u, int v){Edge E={u, v, head[u], false};edge[edgenum] = E;head[u] = edgenum++;}int DFN[N], Low[N], Stack[N], top, Time;int taj;//连通分支标号,从1开始int Belong[N];//Belong[i] 表示i点属于的连通分支bool Instack[N];vector<int> bcc[N]; //标号从1开始void tarjan(int u ,int fa){  DFN[u] = Low[u] = ++ Time ;  Stack[top ++ ] = u ;  Instack[u] = 1 ;  for (int i = head[u] ; ~i ; i = edge[i].nex ){  int v = edge[i].to ;  if(DFN[v] == -1){  tarjan(v , u) ;  Low[u] = min(Low[u] ,Low[v]) ;if(DFN[u] < Low[v]){edge[i].sign = 1;//为割桥}}  else if(Instack[v]) Low[u] = min(Low[u] ,DFN[v]) ; }  if(Low[u] == DFN[u]){  int now;taj ++ ; bcc[taj].clear();do{now = Stack[-- top] ;  Instack[now] = 0 ; Belong [now] = taj ;bcc[taj].push_back(now);}while(now != u) ;}}void tarjan_init(int all){memset(DFN, -1, sizeof(DFN));memset(Instack, 0, sizeof(Instack));top = Time = taj = 0;for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //点标从0开始}vector<int>G[N];int du[N];void suodian(){memset(du, 0, sizeof(du));for(int i = 1; i <= taj; i++)G[i].clear();for(int i = 0; i < edgenum; i++){int u = Belong[edge[i].from], v = Belong[edge[i].to];if(u!=v)G[u].push_back(v), du[v]++;}}bool topsort(){queue<int>q; for(int i = 1; i <= taj; i++)if(du[i] == 0){q.push(i);du[i]=-1;break;}while(!q.empty()){int u = q.front(); q.pop(); du[u] = -1;for(int i = 0; i < G[u].size(); i++){int v = G[u][i]; if(du[v] == -1)continue;du[v] = -1;q.push(v);break;}}for(int i = 1; i <= taj; i++)if(du[i]!=-1)return false;return true;}int main(){int u, v, i, j, T;scanf("%d",&T);while(T--){scanf("%d %d", &n, &m);memset(head, -1, sizeof(head)); edgenum = 0;while(m--)scanf("%d %d",&u,&v), add(u,v);tarjan_init(n);suodian();topsort() ? puts("Yes") : puts("No");}return 0;}/*993 31 22 33 11 02 22 11 22 12 12 05 71 51 22 11 33 14 11 46 81 51 22 11 33 14 11 46 15 75 11 22 11 33 14 11 43 31 22 13 14 41 21 32 43 4*/


 

0 0
原创粉丝点击