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

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

    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

     
     
    题意:有N个山洞m条路,问任意两点x y 能否存在从x到y 或者从y到x。

    思路:注意是或 而不是和。所以缩点后,不是判断强连通为1。
    第一种方法:从入度为0的点 DFS 搜索 最长能到达的路径 如果路径长度等于点数,说明可以从源点访问完所有点。   
     
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int VM=1010;
    const int EM=6010;
    
    struct Edge{
        int to,nxt;
    }edge1[EM],edge2[EM];
    
    int n,m,cnt,dep,top,atype,head1[VM],head2[VM];
    int dfn[VM],low[VM],vis[VM],indeg[VM],outdeg[VM],belong[VM];
    int stack[VM];
    
    void Init(){
        cnt=0, dep=0, top=0, atype=0;
        memset(head1,-1,sizeof(head1));
        memset(head2,-1,sizeof(head2));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        memset(indeg,0,sizeof(indeg));
        memset(outdeg,0,sizeof(outdeg));
        memset(belong,0,sizeof(belong));
    }
    
    void addedge(int cu,int cv,Edge edge[],int head[]){
        edge[cnt].to=cv;
        edge[cnt].nxt=head[cu];
        head[cu]=cnt++;
    }
    
    void Tarjan(int u){
        dfn[u]=low[u]=++dep;
        stack[top++]=u;
        vis[u]=1;
        for(int i=head1[u];i!=-1;i=edge1[i].nxt){
            int v=edge1[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(vis[v])
                low[u]=min(low[u],dfn[v]);
        }
        int j;
        if(dfn[u]==low[u]){
            atype++;
            do{
                j=stack[--top];
                belong[j]=atype;
                vis[j]=0;
            }while(j!=u);
        }
    }
    
    int path[VM],maxdep;
    
    void DFS(int u,int d){
        path[u]=d;
        maxdep=max(maxdep,d);
        for(int i=head2[u];i!=-1;i=edge2[i].nxt){
            int v=edge2[i].to;
            if(path[u]>path[v])
                DFS(v,d+1);
        }
    }
    
    int Solve(){
        int u,v;
        for(u=1;u<=n;u++)
            for(int i=head1[u];i!=-1;i=edge1[i].nxt){
                v=edge1[i].to;
                if(belong[u]!=belong[v]){
                    indeg[belong[v]]++;
                    addedge(belong[u],belong[v],edge2,head2);
                }
            }
         maxdep=0;
         for(u=1;u<=n;u++)
            if(!indeg[u]){
                DFS(u,1);
                break;
            }
        if(maxdep==atype)
            return 1;
        return 0;
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        int t;
        scanf("%d",&t);
        while(t--){
            Init();
            scanf("%d%d",&n,&m);
            int u,v;
            while(m--){
                scanf("%d%d",&u,&v);
                addedge(u,v,edge1,head1);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                    Tarjan(i);
            if(Solve())
                printf("Yes\n");
            else
                printf("No\n");
        }
        return 0;
    }

     

     
     
     

    第二种方法: 只要用拓扑判断入度为0的点是否为1个,如果有多个,就出现在分叉,不可能从x到y。
     
     
    #include <stdio.h>
    #include <string.h>
    #define VM 1005
    #define EM 6005
    
    struct E
    {
        int to,next;
    }edge[EM];
    struct E1
    {
        int frm,to,next;
    }edge1[EM];
    int head[VM],head1[VM],indeg[VM],map[VM][VM];
    int dfn[VM],low[VM],vis[VM],belong[VM],stack[VM];
    int scc,cnt,top,p,n;
    
    void addedge (int cu,int cv)
    {
        edge[p].to = cv;
        edge[p].next = head[cu];
        head[cu] = p++;
    }
    
    void addedge1(int cu,int cv)
    {
        edge1[p].frm = cu;
        edge1[p].to = cv;
        edge1[p].next = head1[cu];
        head1[cu] = p ++;
    }
    void tarjan (int u)
    {
        int v;
        dfn[u] = low[u] = ++cnt;
        stack[top++] = u;
        vis[u] = 1;
        for (int i = head[u];i != -1;i = edge[i].next)
        {
            v = edge[i].to;
            if (!dfn[v])
            {
                tarjan(v);
                low[u] = low[u] > low[v]?low[v]:low[u];
            }
            else if (vis[v]&&low[u] > dfn[v])
                low[u] = dfn[v];
        }
        if (dfn[u] == low[u])
        {
            ++scc;
            do
            {
                v = stack[--top];
                vis[v] = 0;
                belong[v] = scc;
            } while (u != v);
        }
    }
    void sovle ()
    {
        int u;
        scc = top = cnt = 0;
        memset (dfn,0,sizeof(dfn));
        memset (vis,0,sizeof(vis));
        for (u = 1;u <= n;u ++)
            if (!dfn[u])
                tarjan(u);
    }
    
    int topo ()
    {
        int u,v,i,cur,count = 0;;
        for (u = 1;u <= scc;u ++)
            if (!indeg[u])
            {
                count ++;
                cur = u;
            }
        if (count > 1)
            return 0;
        int num = scc;
        while (num --)
        {
            count = 0;
            for (i = head1[cur];i != -1;i = edge1[i].next)
            {
                u = edge1[i].frm;
                v = edge1[i].to;
                //indeg[u] --;
                indeg[v] --;
                if (!indeg[v])
                {
                    count ++;
                    cur = v;
                }
            }
            if (count > 1)
                return 0;
        }
        return 1;
    }
    
    int ans()
    {
        int u,v,i,count = 0;
        memset (indeg,0,sizeof(indeg));
        memset (map,0,sizeof (map));
        for (u = 1;u <= n;u ++)
            for (i = head[u];i != -1;i = edge[i].next)
            {
                v = edge[i].to;
                int j,k;
                j = belong[u];
                k = belong[v];
                if (j != k&& !map[j][k])
                {
                    indeg[k] ++;
                    addedge1 (j,k);
                    map[j][k] = 1;
                }
            }
        if (topo())
            return 1;
        return 0;
    
    }
    
    int main ()
    {
        int t,m,u,v;
        scanf ("%d",&t);
        while (t --)
        {
            p = 0;
            memset (head1,-1,sizeof(head1));
            memset (head,-1,sizeof(head));
            scanf ("%d%d",&n,&m);
            while (m --)
            {
                scanf ("%d%d",&u,&v);
                addedge (u,v);
            }
            sovle ();
            if (ans())
                printf ("Yes\n");
            else
                printf("No\n");
        }
        return 0;
    }
  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/jackge/p/3053969.html
Copyright © 2011-2022 走看看