zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    毛皮立方体
    APPLE buSinEss
    #4613. problem C
    #4614. problem B
    idiots
    熊猫(i)
    圆盘自动机 cell
    小L的占卜
    有趣的数(number)
    「JOISC 2015 Day 1」卡片占卜
  • 原文地址:https://www.cnblogs.com/sweat123/p/5616164.html
Copyright © 2011-2022 走看看