POJ2762 Going from u to v or from v to u?

Description

Going from u to v or from v to u?
In order to make their sons brave, Jiajia and Wind take them to a big cave.
The cave has n rooms, and one-way corridors connecting some rooms. Each time
Wind choose two rooms x and y, and ask one of their little sons go from one to the other.
The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible
but she actually doesn't know how to decide if a task is possible. To make her life easier
Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave
can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
给定一个有向图,判断是否对于任何两个点u,v
总存在u-->v 或者v-->u.

Input

The first line contains a single integer T, the number of test cases.
And followed T cases.The first line for each case contains two integers n, m(0the number of rooms and corridors in the cave. The next m lines each contains two integers u and v
indicating that there is a corridor connecting room u and room v directly.

Output

The output should contain T lines. Write `Yes'
if the cave has the property stated above, or `No' otherwise.

Sample Input

1
3 3
1 2
2 3
3 1

Sample Output

Yes
说白了就是问你这整张图连不连通,这个我们很容易想到强连通分量,既然这样我们就可以考虑缩点,能缩点的一定是满足条件的,那么缩完点之后判断是否是单链并且只有一个出度为0的点,好,既然是这样,如何去判断?除了首尾其余所有的点都只有一个父亲和一个儿子,那不就是单链。还有,如果缩点前是单链,直接输出就好了。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int nex[10001],pre[10001],son[10001],n,m,T,dfn[10001],fa[10001],low[10001],tot,a[10001],b[10001],st[10001],used[10001],popp[10001];
char ch; bool ok;
void read(int &x){
    for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    if (ok) x=-x;
}
inline void add(int x,int y)
{
    nex[++tot]=pre[x];
    fa[y]++;
    son[x]++;
    pre[x]=tot;
}
int top,sum,total,ll,tottt;
inline void dfs(int now)
{
    st[++top]=now;
    sum++;
    dfn[now]=low[now]=sum;
    int ttt=top;
    for(int i=pre[now];i;i=nex[i])
        if(!used[b[i]])
        {
            if(!dfn[b[i]])
                dfs(b[i]);
            low[now]=min(low[now],low[b[i]]);
        }
    if(low[now]==dfn[now])
    {
        total++;
        for(int i=ttt;i<=top;i++)
            used[st[i]]=total;
        top=ttt-1;
    }
}
int tepan()
{
    if(total==1)return 1; 
    int f=0,p=0,l=0;
    for(int i=1;i<=total;i++)
        if(fa[i]==1&&son[i]==1)f++;
        else
        {
            if(fa[i]!=1) 
                p=fa[i];
            if(son[i]!=1)
                l=son[i];
        }
    if(f==total-2&&p==0&&l==0)return 1;
    return 0;
}
int main()
{
    read(T);
    while(T--)
    {
        tot=0;total=0;top=0;int ans=0,ans1=0;
        memset(st,0,sizeof(st));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(used,0,sizeof(used));
        memset(pre,0,sizeof(pre));
        memset(son,0,sizeof(son));
        memset(fa,0,sizeof(fa));
        memset(popp,0,sizeof(popp));
        read(n),read(m);
        for(int i=1;i<=m;i++)
            read(a[i]),read(b[i]),add(a[i],b[i]);
        total=n;
        if(tepan())
        {puts("Yes");continue;}
        total=0;
        tot=0;
        for(int i=1;i<=n;i++)
            if(!used[i])dfs(i);
        memset(son,0,sizeof(son));
        memset(fa,0,sizeof(fa));
        for(int i=1;i<=m;i++)
            if(used[a[i]]!=used[b[i]])add(used[a[i]],used[b[i]]),popp[used[a[i]]]++;
        for(int i=1;i<=total;i++)
            if(!popp[i])ans++;
        if(tepan()&&ans==1)puts("Yes");
        else
            puts("No");
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值