• (连通图 模板题 出度和入度)Network of Schools--POJ--1236


    链接:

    http://poj.org/problem?id=1236

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82833#problem/A

    题意:学校有一些单向网络,现在需要传一些文件

    求:1,求最少需要向几个学校分发文件才能让每个学校都收到,

      2,需要添加几条网络才能从任意一个学校分发都可以传遍所有学校。

    解题思路(参考大神的):

    —        1. 求出所有强连通分量

    —        2. 每个强连通分量缩成一点,则形成一个有向无环图DAG。

    —        3. DAG上面有多少个入度为0的顶点,问题1的答案就是多少

    在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少

    加边的方法:

    要为每个入度为0的点添加入边,为每个出度为0的点添加出边

    假定有 n 个入度为0的点,m个出度为0的点,如何加边?

    把所有入度为0的点编号 0,1,2,3,4 ....N -1

    每次为一个编号为i的入度0点可达的出度0点,添加一条出边,连到编号为(i+1)%N 的那个出度0点,

    这需要加n条边

    若 m <= n,则

    加了这n条边后,已经没有入度0点,则问题解决,一共加了n条边

    若 m > n,则还有m-n个入度0点,则从这些点以外任取一点,和这些点都连上边,即可,这还需加m-n条边。

    所以,max(m,n)就是第二个问题的解

    此外:当只有一个强连通分支的时候,就是缩点后只有一个点,虽然入度出度为0的都有一个,但是实际上不需要增加清单的项了,所以答案是1,0;

    代码:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cstring>
      7 #include<vector>
      8 using namespace std;
      9 #define N 105
     10 
     11 struct Edge{int v, next;}e[N*N];
     12 
     13 int n, Time, bnt, cnt, top;
     14 int low[N], dfn[N], Head[N], sta[N], InStack[N], belong[N];
     15 
     16 void Init()
     17 {
     18     Time = bnt = cnt = top = 0;
     19     memset(low, 0, sizeof(low));
     20     memset(dfn, 0, sizeof(dfn));
     21     memset(Head, -1, sizeof(Head));
     22 }
     23 void Add(int u, int v)
     24 {
     25     e[cnt].v = v;
     26     e[cnt].next = Head[u];
     27     Head[u] = cnt++;
     28 }
     29 
     30 void Tarjan(int u)
     31 {
     32     int j;
     33     low[u] = dfn[u] = ++Time;
     34     InStack[u] = 1;
     35     sta[++top]=u;
     36 
     37     for(j=Head[u]; j!=-1; j=e[j].next)
     38     {
     39         int v = e[j].v;
     40 
     41         if(!dfn[v])
     42         {
     43             Tarjan(v);
     44             low[u] = min(low[u], low[v]);
     45         }
     46         else if(InStack[v])
     47             low[u] = min(low[u], dfn[v]);
     48     }
     49 
     50     if(dfn[u] == low[u])
     51     {
     52         ++bnt;
     53         do
     54         {
     55             j = sta[top--];
     56             InStack[j] = false;
     57             belong[j] = bnt;
     58         }while(u!=j);
     59     }
     60 }
     61 
     62 int main()
     63 {
     64     while(scanf("%d", &n)!=EOF)
     65     {
     66         int u, v, i, j;
     67 
     68         Init();
     69 
     70         for(i=1; i<=n; i++)
     71         {
     72             while(scanf("%d", &v), v)
     73                 Add(i, v);
     74         }
     75 
     76         for(i=1; i<=n; i++)
     77             if(!dfn[i])
     78             Tarjan(i);
     79 
     80         int r[N]={0}, c[N]={0}, rn=0, cn=0;
     81 
     82         for(i=1; i<=n; i++)
     83         for(j=Head[i]; j!=-1; j=e[j].next)
     84         {
     85             u = belong[i], v = belong[e[j].v];
     86             if(u!=v)
     87             {
     88                 c[u]++;
     89                 r[v]++;
     90             }
     91         }
     92 
     93         for(i=1; i<=bnt; i++)
     94         {
     95             if(r[i]==0) rn++;
     96             if(c[i]==0) cn++;
     97         }
     98 
     99         if(bnt == 1)
    100             printf("1
    0
    ");
    101         else
    102             printf("%d
    %d
    ", rn, max(rn, cn));
    103 
    104     }
    105     return 0;
    106 }
    勿忘初心
  • 相关阅读:
    侧边工具栏
    proguard 使用说明
    人员组成
    google play
    大数据平台相关
    HttpClient
    库克
    html5 开发 android 注意点
    htm5 动画制作 工具
    JAVA取得WEBROOT物理路径
  • 原文地址:https://www.cnblogs.com/YY56/p/4709320.html
Copyright © 2020-2023  润新知