poj 2762 Going from u to v or from v to u? (强联通分量缩点 + 欧拉回路或通路)

来源:互联网 发布:ubuntu opencv安装 编辑:程序博客网 时间:2024/05/22 03:13

大概题意:n个点,m条单向的路,问任意的x和y之间是否可达。注意“The son can either go from x to y, or from y to x.”是or,不是and。所以并不是一定只能有一个强联通分量。

方法:强联通分量缩点+欧拉回路或通路。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;vector<int>e[1002];int n,m,a,b,t,in[1002],out[1002],p[1002];int y,ind,cnt,stack[1002],instack[1002],dfn[1002],low[1002],fa[1002];int find(int x){    if(p[x]!=x) return find(p[x]);    return p[x];}void mege(int a,int b){    a=find(a);b=find(b);    if(a!=b)    p[b]=a;}void tarjan(int i){    int j,k;    dfn[i]=low[i]=++ind;    instack[i]=1;    stack[y++]=i;    for(j=0;j<e[i].size();j++)    {        k=e[i][j];        if(!dfn[k])        {            tarjan(k);            low[i]=min(low[i],low[k]);        }        else if(instack[k])        low[i]=min(low[i],dfn[k]);    }    if(dfn[i]==low[i])    {        int v;        cnt++;        do        {            v=stack[--y];            fa[v]=cnt;            instack[v]=0;        }while(i!=v);    }}int main(){    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        int i,j;        for(i=1;i<=1001;i++)        e[i].clear();        for(i=1;i<=m;i++)        {            scanf("%d%d",&a,&b);            e[a].push_back(b);        }        memset(dfn,0,sizeof(dfn));        memset(instack,0,sizeof(instack));        memset(stack,0,sizeof(stack));        memset(fa,0,sizeof(fa));        y=cnt=ind=0;        for(i=1;i<=n;i++)        {            if(!dfn[i]) tarjan(i);        }        for(i=1;i<=cnt;i++)        p[i]=i;        memset(in,0,sizeof(in));        memset(out,0,sizeof(out));        for(i=1;i<=n;i++)        {            for(j=0;j<e[i].size();j++)            {                int k=e[i][j];                if(fa[i]!=fa[k])                {                    in[fa[k]]++;                    out[fa[i]]++;                    mege(fa[i],fa[k]);                }            }        }        int tag=0,x=0,y=0,other=0;        for(i=1;i<=cnt;i++)        {            if(find(i)==i) tag++;            if(in[i]!=out[i])            {                if(in[i]+1==out[i]) x++;                else if(in[i]-1==out[i]) y++;                else other++;            }        }        if(tag==1&&((x==0&&y==0)||(x==1&&y==1))&&other==0)        printf("Yes\n");        else        printf("No\n");    }    return 0;}


原创粉丝点击