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;
    }
  • 相关阅读:
    SELECT IDENT_CURRENT(tableName)和自增长列的纠结
    [置顶]c# 设计模式(1)一 创建型
    我们互联网生活因家庭服务器改变
    互联网创业不妨先放下平台梦
    影响未来的应用ifttt,互联网自主神经系统的又一个有力证据
    什么是ifttt,ifttt怎么玩? ifttt操作体验具体步骤
    杰出企业家的20个好习惯
    折叠分组表格中重用Cell导致的问题
    使用AChartEngine画折线图
    MSSQL获取当前插入的ID号及在高并发的时候处理方式
  • 原文地址:https://www.cnblogs.com/jackge/p/3053969.html
Copyright © 2011-2022 走看看