【POJ2762】Going from u to v or from v to u?(tarjan+缩点+拓扑排序)

来源:互联网 发布:mac视频怎么全屏 编辑:程序博客网 时间:2024/04/27 10:26

记录一个菜逼的成长。。

题目链接
题目大意:
判断给你的有向图是否为单向连通图

用tarjan算法求出强连通分量,以强连通分量为顶点建新图(tarjan算法O(n+m))
如果一个DAG是单向连通图当且仅当它的拓扑序唯一
也就是说拓扑排序时队列中的元素不能大于1

虽然这题点数较小,可以用矩阵,但是前向星可以适应更大的点数

#include <cstdio>#include <queue>#include <stack>#include <cstring>#include <algorithm>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))const int maxn = 50000 + 10;int head[maxn],cnt;int head1[maxn],cnt1;struct Edge{    int next,to;}edge[maxn],g[maxn];void add(int u,int v){    edge[cnt].to = v;    edge[cnt].next = head[u];    head[u] = cnt++;}void add1(int u,int v){    g[cnt1].to = v;    g[cnt1].next = head1[u];    head1[u] = cnt1++;}int instack[maxn],dfn[maxn],low[maxn],ind,num,belong[maxn];stack<int>sta;int d[maxn];///入度void tarjan(int u){    ///dfn(u)为时间戳,即dfs序    ///Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号    dfn[u] = low[u] = ++ind;    instack[u] = 1;    sta.push(u);    for( int i = head[u]; ~i; i = edge[i].next ){        int v = edge[i].to;        if(!dfn[v]){            tarjan(v);            low[u] = min(low[u],low[v]);        }        else if(instack[v]){            low[u] = min(low[u],dfn[v]);        }    }    if(dfn[u] == low[u]){        num++;        int v;        do{            v = sta.top();            sta.pop();            instack[v] = 0;            belong[v] = num;///点v属于第num个强连通分量        }while(u != v);    }}void init(){    while(!sta.empty())sta.pop();    cl(head,-1),cnt = 0;    cl(head1,-1),cnt1 = 0;    cl(instack,0),cl(dfn,0),cl(low,0);    ind = 0;    num = 0;    cl(belong,0);    cl(d,0);    cl(g,0);}bool topsort(){    queue<int>q;    for( int i = 1; i <= num; i++ ){        if(!d[i])q.push(i);    }    if(q.size() > 1)return false;    while(!q.empty()){        int f = q.front();q.pop();        for( int i = head1[f]; ~i; i = g[i].next ){            int v = g[i].to;            if(!--d[v])                q.push(v);        }        if(q.size() > 1)return false;    }    return true;}int main(){    int T;scanf("%d",&T);    while(T--){        init();        int n,m;        scanf("%d%d",&n,&m);        for( int i = 0; i < m; i++ ){            int u,v;            scanf("%d%d",&u,&v);            add(u,v);        }        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; j = edge[j].next ){                if(belong[i] != belong[edge[j].to]){                    d[belong[edge[j].to]]++;                    add1(belong[i],belong[edge[j].to]);                }            }        }        puts(topsort()?"Yes":"No");    }    return 0;}
0 0
原创粉丝点击