poj 2762 Going from u to v or from v to u?

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 19390 Accepted: 5224
Description

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?
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(0 < n < 1001,m < 6000), the 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,那么他们一定不可能到达对方,所以拓补排序,每次看是否有两个点同时入度为0。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;
const int MAXM = 100005;
const int MAXN = 10005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int n,m,T;
int num,col_num,col[MAXN];
int dfn[MAXN],low[MAXN];
int head[MAXN],cnt,fr[MAXM],se[MAXM];
int to[MAXM],nxt[MAXM];
int head_[MAXN],cnt_;
int to_[MAXM],nxt_[MAXM];
int stk[MAXN],top,du[MAXN];
bool vis[MAXN];
queue<int> Q;

inline void add(int bg,int ed){
    to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}

inline void add_(int bg,int ed){
    to_[++cnt_]=ed,nxt_[cnt_]=head_[bg],head_[bg]=cnt_;
}

inline void tarjan(int x){
    dfn[x]=low[x]=++num;
    stk[++top]=x;vis[x]=1;
    for(register int i=head[x];i;i=nxt[i]){
        int u=to[i];
        if(!dfn[u]){
            tarjan(u);
            low[x]=min(low[x],low[u]);
        }
        else if(vis[u])
            low[x]=min(low[x],dfn[u]);
    }
    if(low[x]==dfn[x]){
        vis[x]=0;col[x]=++col_num;
        while(stk[top]!=x){
            vis[stk[top]]=0;
            col[stk[top--]]=col_num;
        }
        top--;
    }
}

int main(){
    T=rd();
    while(T--){
        bool flag=0;
        for(register int i=1;i<=10000;i++)
            dfn[i]=low[i]=col[i]=du[i]=vis[i]=head[i]=head_[i]=0;
        cnt=top=0;num=col_num=0;
        while(Q.size()) Q.pop();
        n=rd();m=rd();
        for(register int i=1;i<=m;i++){
            int x=rd(),y=rd();
            add(x,y);
            fr[i]=x;se[i]=y;
        }
        for(register int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        for(register int i=1;i<=m;i++)
            if(col[fr[i]]!=col[se[i]])  
                add_(col[fr[i]],col[se[i]]),du[col[se[i]]]++;
        for(register int i=1;i<=col_num;i++)
            if(!du[i]){
                if(Q.size()) {flag=1;break;}
                Q.push(i);
            } 
        if(flag==1) {puts("No");continue;}
        while(Q.size()){
            int x=Q.front();Q.pop();
            for(register int i=head_[x];i;i=nxt_[i]){
                int u=to_[i];
                du[u]--;
                if(du[u]==0){
                    if(Q.size()) {flag=1;break;}
                    Q.push(u);
                }
            }
            if(flag==1) break;
        }
        if(flag==1) puts("No");
        else puts("Yes");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9676910.html