zoukankan      html  css  js  c++  java
  • poj2186 Popular Cows

    题意:

    给定一个有向图,求有多少个顶点是由任何顶点出发都可达的。
    顶点数<= 10,000,边数 <= 50,000

    思路:

    1. Korasaju算法把图进行强连通分量分解,在分解的同时得到各个强连通分量拓扑序。唯一可能成为解的就是拓扑序最后的强连通分量,最后再检查这个强连通分量是否能从各个顶点均可达即可。

    2. Tarjan算法。

    实现:

    1.

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <vector>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 vector<int> G[10005], G_t[10005], res;
     8 int n, m, x, y, cmp[10005];
     9 bool vis[10005];
    10 void dfs(int x)
    11 {
    12     vis[x] = true;
    13     for (int i = 0; i < G[x].size(); i++)
    14     {
    15         if (!vis[G[x][i]])
    16             dfs(G[x][i]);
    17     }
    18     res.push_back(x);
    19 }
    20 
    21 void rdfs(int x, int k)
    22 {
    23     vis[x] = true;
    24     cmp[x] = k;
    25     for (int i = 0; i < G_t[x].size(); i++)
    26     {
    27         if (!vis[G_t[x][i]])
    28         {
    29             rdfs(G_t[x][i], k);
    30         }
    31     }
    32 }
    33 
    34 int main()
    35 {
    36     while (cin >> n >> m)
    37     {
    38         for (int i = 1; i <= n; i++)
    39         {
    40             G[i].clear();
    41             G_t[i].clear();
    42         }
    43         res.clear();
    44         for (int i = 0; i < m; i++)
    45         {
    46             scanf("%d %d", &x, &y);
    47             G[x].push_back(y);
    48             G_t[y].push_back(x);
    49         }
    50         memset(vis, 0, sizeof(vis));
    51         for (int i = 1; i <= n; i++)
    52         {
    53             if (!vis[i])
    54                 dfs(i);
    55         }
    56         memset(vis, 0, sizeof(vis));
    57         int k = 0;
    58         for (int i = res.size() - 1; i >= 0; i--)
    59         {
    60             if (!vis[res[i]])
    61             {
    62                 rdfs(res[i], k++);
    63             }
    64         }
    65         int cnt = 0, tmp = 0;
    66         for (int i = 1; i <= n; i++)
    67         {
    68             if (cmp[i] == k - 1)
    69             {
    70                 cnt++;
    71                 tmp = i;
    72             }
    73         }
    74         memset(vis, 0, sizeof(vis));
    75         rdfs(tmp, 0);
    76         for (int i = 1; i <= n; i++)
    77         {
    78             if (!vis[i])
    79             {
    80                 cnt = 0;
    81                 break;
    82             }
    83         }
    84         printf("%d
    ", cnt);
    85     }
    86     return 0;
    87 }

    2.

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <vector>
      4 #include <cstring>
      5 #include <stack>
      6 #include <algorithm>
      7 using namespace std;
      8 
      9 vector<int> G[10005];
     10 int index = 1, now = 1, low[10005], dfn[10005], in[10005], cmp[10005], out[10005];
     11 int n, m, x, y;
     12 stack<int> s;
     13 
     14 void tarjan(int x)
     15 {
     16     dfn[x] = low[x] = index++;
     17     s.push(x);
     18     in[x] = true;
     19     for (int i = 0; i < G[x].size(); i++)
     20     {
     21         int v = G[x][i];
     22         if (!dfn[v])
     23         {
     24             tarjan(v);
     25             low[x] = min(low[x], low[v]);
     26         }
     27         else if (in[v])
     28         {
     29             low[x] = min(low[x], dfn[v]);
     30         }
     31     }
     32     if (low[x] == dfn[x])
     33     {
     34         while (s.top() != x)
     35         {
     36             cmp[s.top()] = now;
     37             in[s.top()] = false;
     38             s.pop();
     39         }
     40         cmp[s.top()] = now++;
     41         in[s.top()] = false;
     42         s.pop();
     43     }
     44 }
     45 
     46 int main()
     47 {
     48     while (cin >> n >> m)
     49     {
     50         for (int i = 1; i <= n; i++)
     51         {
     52             G[i].clear();
     53         }
     54         memset(cmp, 0, sizeof(cmp));
     55         memset(out, 0, sizeof(out));
     56         memset(low, 0, sizeof(low));
     57         memset(dfn, 0, sizeof(dfn));
     58         memset(in, 0, sizeof(in));
     59         index = now = 1;
     60         while (!s.empty())
     61         {
     62             s.pop();
     63         }
     64         for (int i = 0; i < m; i++)
     65         {
     66             scanf("%d %d", &x, &y);
     67             G[x].push_back(y);
     68         }
     69         for (int i = 1; i <= n; i++)
     70         {
     71             if (!dfn[i])
     72             {
     73                 tarjan(i);
     74             }
     75         }
     76         int cnt = 0;
     77         for (int i = 1; i <= n; i++)
     78         {
     79             if (cmp[i] == 1)
     80                 cnt++;
     81         }
     82         for (int i = 1; i <= n; i++)
     83         {
     84             for (int j = 0; j < G[i].size(); j++)
     85             {
     86                 int v = G[i][j];
     87                 if (cmp[i] != cmp[v])
     88                 {
     89                     out[cmp[i]]++;
     90                 }
     91             }
     92         }
     93         int num = 0;
     94         for (int i = 1; i < now; i++)
     95         {
     96             if (!out[i])
     97             {
     98                 if (!num)
     99                     num++;
    100                 else
    101                 {
    102                     cnt = 0;
    103                     break;
    104                 }
    105             }
    106         }
    107         printf("%d
    ", cnt);
    108     }
    109     return 0;
    110 }

    总结:

    有向图进行进行强连通分量分解并缩点之后可以得到一个DAG。

    如果有多于一个出度为0的缩点则解为0。

  • 相关阅读:
    [oracle 使用(1)] win7/10 下Oracle10g的安装与卸载
    [原创]利用爬虫技术获取网页数据,以及想要的指定数据
    [mysql使用(1)] 64位Linux下安装mysql-5.7.13-linux-glibc2.5-x86_64
    aop 常见的问题
    Git技巧:右键菜单怎么去除?
    jrebel激活
    python与mysql连接
    linux下mysql的安装
    Linux下jdk和tomcat安装
    Lotto
  • 原文地址:https://www.cnblogs.com/wangyiming/p/6357988.html
Copyright © 2011-2022 走看看