zoukankan      html  css  js  c++  java
  • POJ 2762 Going from u to v or from v to u?(半连通图)

     

    题目大意

     

    给你一个 n(0<n<1001) 个节点 m(m<6000) 条边的有向图,对于图中的任意两个节点 u 和 v,问能否从 u 走到 v 或者从 v 走到 u

    PS:这其实是《算法导论》中讲“强连通分量”的最后一道习题

     

    做法分析

     

    由于强连通分量重的点肯定能够满足题目的要求,所以可以先将图“化简”,变成 DAG(Directed Acyclic Graph)

     

    首先:如果当前的 DAG 有不止一个入读为 0 的点,那么这些点之间肯定不能相互到达,还要明确的是,当前的 DAG 中至少有一个节点的入读为 0(如果没有节点的入读为 0,这些节点肯定能够形成环,和 DAG 中的 Acyclic 矛盾,前面的缩点工作做的就不彻底)

    也就是说,现在我们要考虑的就是只有一个点的入读为 0 的情况,这个入读为 0 的点肯定能够到达图中所有的点!

    然后我们将这个入读为 0 的点删掉,考虑剩下的 DAG,由于我们只需要考虑两个点之间是否可以从一个点到达另一个点,那么,当前我们要考虑的就是当前的 DAG 中,入读为 0 的点是否只有一个就行了!(还是一样的道理,如果有两个以上的点,这些点之间是不可到达的)

     

    于是思路清晰了:

            向将原图缩点,形成 DAG(重新建图是必须的啦)

            对新建好的图拓扑排序:

                    每次判断当前是否只有一个点的入读为 0,如果不止一个,跳出拓扑排序过程,输出 No

                    将那个入读为 0 的点从新图中删掉,再进行下一轮判断

                    如果当前的 DAG 中只剩一个节点,跳出拓扑排序过程,输出 Yes

    缩点当然用 Tarjan 了

     

    参考代码

    POJ 2762
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <vector>
     5 #include <stack>
     6 
     7 using namespace std;
     8 
     9 const int N=1006;
    10 
    11 vector <int> arc[N], adj[N];
    12 int n, m, t, T, ind;
    13 int dfn[N], low[N], id[N], in[N];
    14 bool vs[N];
    15 stack <int> s;
    16 
    17 void tarjan(int u)
    18 {
    19     vs[u]=1, s.push(u);
    20     dfn[u]=low[u]=T++;
    21     int len=(int)arc[u].size();
    22     for(int i=0; i<len; i++)
    23     {
    24         int v=arc[u][i];
    25         if(dfn[v]==-1)
    26         {
    27             tarjan(v);
    28             if(low[u]>low[v]) low[u]=low[v];
    29         }
    30         else if(vs[v] && low[u]>dfn[v]) low[u]=dfn[v];
    31     }
    32     if(low[u]==dfn[u])
    33     {
    34         for(int v; 1; )
    35         {
    36             v=s.top();
    37             s.pop(), vs[v]=0;
    38             id[v]=ind;
    39             if(v==u) break;
    40         }
    41         ind++;
    42     }
    43 }
    44 
    45 int main()
    46 {
    47     scanf("%d", &t);
    48     for(int ca=1; ca<=t; ca++)
    49     {
    50         scanf("%d%d", &n, &m);
    51         for(int i=0; i<=n; i++) dfn[i]=-1, vs[i]=0, arc[i].clear();
    52         while(!s.empty()) s.pop();
    53         for(int i=0, a, b; i<m; i++)
    54         {
    55             scanf("%d%d", &a, &b);
    56             arc[a].push_back(b);
    57         }
    58         ind=T=0;
    59         for(int i=1; i<=n; i++) if(dfn[i]==-1) tarjan(i);
    60         for(int i=0; i<ind; i++) adj[i].clear(), in[i]=0, vs[i]=0;
    61         for(int i=1; i<=n; i++)
    62         {
    63             int len=(int)arc[i].size(), u=id[i];
    64             for(int j=0; j<len; j++)
    65             {
    66                 int v=id[arc[i][j]];
    67                 if(u!=v) adj[u].push_back(v), in[v]++;
    68             }
    69         }
    70         int tot=ind, flag=1;
    71         while(flag && tot>1)
    72         {
    73             int p=-1, cnt=0;
    74             for(int i=0; i<ind; i++)
    75                 if(!vs[i] && in[i]==0) p=i, cnt++;
    76             if(cnt!=1)
    77             {
    78                 flag=0;
    79                 break;
    80             }
    81             int len=(int)adj[p].size();
    82             for(int i=0; i<len; i++) in[adj[p][i]]--;
    83             tot--, vs[p]=1;
    84         }
    85         if(flag) printf("Yes\n"); else printf("No\n");
    86     }
    87     return 0;
    88 }

    AC通道

    POJ 2762 Going from u to v or from v to u?

  • 相关阅读:
    es6中新增的字符串函数
    模板字符串
    jsp注释
    EL表达式(自己看的)
    在禁用cookie时操作Session
    urlEncoder和urlDecoder的作用和使用
    jsp中写java代码的方法
    通过类加载器在WEB应用中获取资源文件路径
    统计在线人数
    Mysql数据库操作简单版
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/2962635.html
Copyright © 2011-2022 走看看