zoukankan      html  css  js  c++  java
  • POJ 2762 Going from u to v or from v to u?

    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 17689   Accepted: 4745

    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

    Source

     
    题目大意

    给出一些点,和他们之间的有向边,如果图中任意两点 x,y 之间满足 x 可以到达 y 或者 y 可以到达 x ,就输出“Yes”,否则输出“No”

    因为n>1000 所以挨个判断是不可取的 

    所以我们用tarjan 求出强连通分量的个数

    然后判断这几个强连通分量在不在一条链上就可以了 

    tarjan缩点+拓扑排序

    屠龙宝刀点击就送

    #include <cstring>
    #include <ctype.h>
    #include <cstdio>
    #include <queue>
    #define M 6005
    #define N 1500
    using namespace std;
    void read(int &x)
    {
        x=0;bool f=0;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-') f=1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        x=f?(~x)+1:x;
    }
    int in[N],g[N][N],tim,dfn[N],col[N],sumcol,low[N],T,n,m,head[N],cnt,stack[N],top;
    bool instack[N],vis[N];
    struct node
    {
        int next,to;
    }edge[M];
    void add(int u,int v)
    {
        edge[++cnt].next=head[u];
        edge[cnt].to=v;
        head[u]=cnt;
    }
    int min(int a,int b)
    {
        return a>b?b:a;
    }
    void dfs(int x)
    {
        stack[++top]=x;
        instack[x]=1;
        vis[x]=1;
        low[x]=dfn[x]=++tim;
        for(int i=head[x];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(instack[v]) low[x]=min(low[x],dfn[v]);
            else if(!vis[v])
            {
                dfs(v);
                low[x]=min(low[x],low[v]);
            }
        }
        if(low[x]==dfn[x])
        {
            sumcol++;
            while(x!=stack[top])
            {
                instack[stack[top]]=0;
                col[stack[top--]]=sumcol;
            }
            instack[stack[top]]=0;
            col[stack[top--]]=sumcol;
        }
    }
    bool judge()
    {
        queue<int>q;
        for(int i=1;i<=sumcol;i++)
        if(!in[i]) q.push(i);
        if(q.size()>1) return false;
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            for(int i=1;i<=sumcol;i++)
            if(g[now][i])
            {
                in[i]--;
                if(!in[i]) q.push(i);
            }
            if(q.size()>1) return false;
        }
        return true;
    }
    int main()
    {
        read(T);
        for(;T--;)
        {
            memset(head,0,sizeof(head));
            memset(dfn,0,sizeof(dfn));
            memset(vis,0,sizeof(vis));
            memset(instack,0,sizeof(instack));
            memset(col,0,sizeof(col));
            memset(low,0,sizeof(low));
            memset(in,0,sizeof(in));
            memset(g,0,sizeof(g)); 
            tim=0;top=0;sumcol=0;cnt=0;
            bool f=false;
            read(n);
            read(m);
            for(int x,y,i=1;i<=m;i++)
            {
                read(x);
                read(y);
                add(x,y);
            }
            for(int i=1;i<=n;i++)
            if(!vis[i]) dfs(i);
            if(sumcol==1) {printf("Yes
    ");continue;}
            for(int i=1;i<=n;i++)
            {
                for(int j=head[i];j;j=edge[j].next)
                {
                    int v=edge[j].to;
                    if(i!=v&&col[i]!=col[v])
                    {
                        g[col[i]][col[v]]=1;
                        in[col[v]]++;
                    }
                }
            }
            if(judge()) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    HDU 1982 Kaitou Kid The Phantom Thief (1)
    HDU 1984 Mispelling4
    HDU 2546 饭卡
    HDU 1009 FatMouse' Trade
    在VC 中如何隐藏一个主程序窗口
    .菜单项
    SetClassLong,GetClassLong 动态改变光标
    .窗口捕获鼠标
    .主窗口向子控件发送消息
    线段树 1698 Just a Hook 区间set更新
  • 原文地址:https://www.cnblogs.com/ruojisun/p/6790222.html
Copyright © 2011-2022 走看看