poj 2762

来源:互联网 发布:mysql服务 启动 linux 编辑:程序博客网 时间:2024/05/16 15:04

题意:

由 m 条单向边相连的图中,判断任意两点是否单向相通(u -> v 存在,即成立u 到 v 单向相通,即 v -> u 不一定要存在)

思路:

第一步:缩点(tarjan算法)。在一个强连通分量中任意两点一定相通(双向的)。

第二步:判断是否能从一个点搜到每个点,且每个点历遍顺序为 1~n  ==> 拓扑排序,每次入队的点有且只有一个,直至排完 n 个点。

记录完毕。

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;int min( int a, int b ){ return a < b ? a : b; }const int maxn = 1100;const int inf = 1000000000;vector<int>edge[maxn], redge[maxn];int n, m;int tmpdfn, dfn[maxn], low[maxn], inst[maxn], belong[maxn], st[maxn], top, scnt, in[maxn];void tarjan( int u ){int i, v, t, size;low[u] = dfn[u] = tmpdfn++;st[top++] = u;inst[u] = 1;size = edge[u].size();for( i = 0; i < size; i++ ){v = edge[u][i];if( dfn[v] == -1 ){tarjan( v );low[u] = min( low[u], low[v] );}else if( inst[v] )low[u] = min( low[u], dfn[v] );}if( dfn[u] == low[u] ){do{ belong[t = st[--top]] = scnt; inst[t] = 0; }while( t != u );scnt++;}}bool SCC(){int i;top = 0;tmpdfn = scnt = 1;memset( dfn, -1, sizeof(dfn) );memset( inst, 0, sizeof(inst) );for( i = 1; i <= n; i++ )if( dfn[i] == -1 )tarjan( i );return true;}void rebuild(){int i, u, v, size;for(i = 1; i < scnt; i++)redge[i].clear();memset(in, 0, sizeof(in));for(u = 1; u <= n; u++){size = edge[u].size();for(i = 0; i < size; i++){v = edge[u][i];if(belong[u] != belong[v]){redge[belong[u]].push_back( belong[v] );in[belong[v]]++;}}}}bool topusort(){int queue[maxn], front, rear, i, u, v, size;front = rear = 0;for(i = 1; i < scnt; i++)if(!in[i])queue[rear++] = i;while(rear - front == 1){u = queue[front++];size = redge[u].size();for(i = 0; i < size; i++){v = redge[u][i];in[v]--;if(!in[v])queue[rear++] = v;}}if(front == scnt - 1)return true;else return false;}int main(){int T, i, u, v;scanf( "%d", &T );while( T-- ){scanf( "%d%d", &n, &m );for(i = 1; i <= n; i++)edge[i].clear();while( m-- ){scanf( "%d%d", &u, &v );if(u != v)edge[u].push_back( v );}SCC();rebuild();if(topusort())puts("Yes");else puts("No");}return 0;}