poj 2762 Going from u to v or from v to u? 强连通+拓扑排序

版权声明:本博客内容基本为原创,如有问题欢迎联系,未经允许请勿转载 https://blog.csdn.net/qq_41955236/article/details/82111533

Going from u to v or from v to u?

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 19520   Accepted: 5256

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

题意:

    给你n个点,m条边,问这个图能否达到以下条件,随意从1~n中任意选择两个点x和y,总是存在一条路可以从x走到y或者从y走到x;

扫描二维码关注公众号,回复: 2994311 查看本文章

做法:

     如果题意中把或者改成并且的话,这道题就是一道强连通分量水题,只要判断是不是全图是一个强连通就好了,但是因为是胡或者,所以我们应该先再强连通缩点,在没有环的情况下进行考虑,如果在没有环之后留下来的是一条链,则永远可以从一个点到达另一个点,这样我们就要用拓扑排序来考虑,而且因为必须是一条链(如果是树形的话,子树之间就不能相互走到了),所以拓扑排序的时候每次队列中只能有一个点。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
#include<queue>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=100050;
int n,m,head[maxn],now;
int belong[maxn],qiang,dfn[maxn],low[maxn],cnt;
int in[maxn];
stack<int> sa;
vector<int> ve[maxn];
struct node{
    int from,to,next;
}e[50005];
void add(int u,int v){
    e[now].from=u;e[now].to=v;
    e[now].next=head[u],head[u]=now++;
}
void tarjan(int x){
    dfn[x]=low[x]=++cnt;
    sa.push(x);
    for(int i=head[x];~i;i=e[i].next){
        int v=e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else if(!belong[v]) low[x]=min(low[x],low[v]);
    }
    if(dfn[x]==low[x]){
        qiang++;
        while(1){
            int u=sa.top();sa.pop();
            belong[u]=qiang;
            if(u==x) break;
        }
    }
}
int topo(){
    int flag=0;
    queue<int> q;
    for(int i=1;i<=qiang;i++){
        if(!in[i]) q.push(i);
    }
    while(!q.empty()&&!flag){
        int u=q.front();q.pop();
        if(!q.empty()) flag=1;
        for(int i=0;i<ve[u].size();i++){
            int t=ve[u][i];
            if(--in[t]==0){
                q.push(t);
            }
        }
    }
    return !flag;
}
void init(){
    mem(head,-1); mem(low,0);
    mem(dfn,0); mem(belong,0);
    mem(in,0); qiang=cnt=now=0;
    for(int i=0;i<=1001;i++)
        ve[i].clear();
    while(!sa.empty()) sa.pop();
}
int main(){
    int t,x,y;
    cin>>t;
    while(t--){

        scanf("%d%d",&n,&m);
         init();
        for(int i=0;i<m;i++){
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        for(int i=0;i<now;i++){
            int fx=belong[e[i].from],fy=belong[e[i].to];
            if(fx!=fy){
                ve[fx].push_back(fy);
                in[fy]++;
            }
        }
        int ans=topo();
        if(ans) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/82111533