poj2762 缩点+topo排序

Going from u to v or from v to u?
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 16486   Accepted: 4386

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
     
题意:
有一张有向图,然后问对于任意的2个点,是否存在x可以到达y,或者y能够到达x。
 
思路:
可以先强连通缩点,这样就没有环的情况。然后这样就是一张新的图。也就是相当于在新的图中判断任意2个点能否存在一条路径。这可以用topo排序来解决。如果存在2个点,他们的入度为0,说明这2个点是不能相互到达的。
 
/*
 * Author:  sweat123
 * Created Time:  2016/6/25 12:33:09
 * File Name: main.cpp
 */
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 20000;
struct node{
    int from;
    int to;
    int next;  
}edge[MAXN*1000];
int pre[MAXN],vis[MAXN],dfn[MAXN],low[MAXN],n,m,ind;
int f[MAXN],num,k;
stack<int>s;
void add(int x,int y){
    edge[ind].from = x;
    edge[ind].to = y;
    edge[ind].next = pre[x];
    pre[x] = ind ++;   
}
void dfs(int rt){
    vis[rt] = 1;
    dfn[rt] = low[rt] = ++k;
    s.push(rt);
    for(int i = pre[rt]; i != -1; i = edge[i].next){
        int t = edge[i].to;
        if(!dfn[t]){
            dfs(t);
            low[rt] = min(low[rt],low[t]);
        } else if(vis[t]){
            low[rt] = min(low[rt],dfn[t]);
        }
    }
    if(low[rt] == dfn[rt]){
        ++ num;
        while(!s.empty()){
            int tp = s.top();
            s.pop();
            vis[tp] = 0;
            f[tp] = num;
            if(tp == rt)break;
        }   
    }
}
int x[MAXN],y[MAXN],ans,in[MAXN];
int ok(){
    queue<int>q;
    for(int i = 1; i <= num; i++){
        if(in[i] == 0){
            q.push(i);
        }     
    }   
    if(q.size() > 1)return 0;
    while(!q.empty()){
        int tp = q.front();
        q.pop();
        for(int i = pre[tp]; i != -1; i = edge[i].next){
            int t = edge[i].to;
            in[t] --;
            if(in[t] == 0){
                q.push(t);   
            }
        }   
        if(q.size() > 1)return 0;
    }
    return 1;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        ind = 0;
        while(!s.empty())s.pop();
        memset(pre,-1,sizeof(pre));
        for(int i = 1; i <= m; i++){
            scanf("%d%d",&x[i],&y[i]);
            add(x[i],y[i]);
        }   
        k = 0;
        num = 0;
        memset(vis,0,sizeof(vis));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(f,0,sizeof(f));
        for(int i = 1; i <= n; i++){
            if(!dfn[i])dfs(i); 
        }
        memset(pre,-1,sizeof(pre));
        memset(in,0,sizeof(in));
        int ret = ind;
        for(int i = 0; i < ret; i++){
            int u = f[edge[i].from];
            int v = f[edge[i].to];
            if(u != v){
                add(u,v);
                in[v] ++;
            }
        }
        if(ok()){
            printf("Yes
");  
        } else{
            printf("No
");   
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sweat123/p/5616164.html