zoukankan      html  css  js  c++  java
  • POJ 1236 Network of Schools

    题目大意:

    给定一个有向图,求:
    1) 至少要选几个顶点,才能做到从这些顶点出
       发,可以到达全部顶点
    2) 至少要加多少条边,才能使得从任何一个顶
     点出发,都能到达全部顶点
       顶点数<= 100

    有用的定理:

    有向无环图中所有入度不为0的点,。一定可以由某个入度为0的点出发可达由于无环,所以从任何入度不为0的点往回走必然终止于一个入度为0的点

    解题思路:

    1. 求出所有强连通分量

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

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

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

     加边的方法:要为每个入度为0的点添加入边,为每个出度为0的点添加出边假定有 n 个入度为0的点,m个出度为0的点,max(m,n)就是第二个问题的解(证明难,略)

     但是比较好想, 我要让那些入度为0,和 出度为 0,的点变为不为 0,这样我们可以形成完全联通,我们一个入度为 0 的连接一个出度为 0 的,可以消失两对,剩下的,我们每个

    再随便加一条边就可以了。

    当我们求出强联通分量之后就可以,然后重新构图, 最后得出结果, 有一个答案要特殊判断一下, 因为只有一个强联通分量的时候是不需要多加边,因此要特殊判断一下。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <cstring>
    usingnamespace std;
    #define INF 0xfffffff
    #define maxn 105
    #define min(a,b) (a<b?a:b)
    bool InStack[maxn];
    int low[maxn], dfn[maxn], Stack[maxn], top, time, cnt;
    int maps[maxn][maxn];
    int belong[maxn];
    int n;
    vector<int> G[maxn];
    
    void Init()
    {
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(InStack, false, sizeof(InStack));
        memset(maps, 0, sizeof(maps));
        cnt = time = top = 0;
    
        for(int i=0; i<=n; i++)
            G[i].clear();
    }
    
    void Tarjan(int u)
    {
        low[u] = dfn[u] = ++time;
        Stack[top++] = u;
        InStack[u] = true;
        int len = G[u].size(), v;
    
        for(int i=0; i<len; i++)
        {
            v = G[u][i];
    
            if( !low[v] )
            {
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            elseif( InStack[v] )
            {
                low[u] = min(low[u], dfn[v]);
            }
        }
    
        if(low[u] == dfn[u])
        {
            do
            {
                v = Stack[--top];
                belong[v] = cnt;
                InStack[v] = false;
            }while(u != v);
            cnt ++;
        }
    }
    
    void solve()
    {
        int InDegree[maxn] = {0};
        int OutDegree[maxn] = {0};
        int In = 0, Out = 0;
    
        for(int i=1; i<=n; i++)
        {
            if(!low[i])
                Tarjan(i);
        }
        for(int i=1; i<=n; i++)
        {
            int len = G[i].size(), v;
            for(int j=0; j<len; j++)
            {
                v = G[i][j];
                maps[belong[i] ][belong[v] ] = 1;
            }
        }
    
        for(int i=0; i<cnt; i++)
        {
            for(int j=0; j<cnt; j++)
            {
                if( i == j)
                    continue;
    
                if(maps[i][j])
                {
                    InDegree[j] ++;
                    OutDegree[i] ++;
                }
            }
        }
    
        for(int i=0; i<cnt; i++)
        {
            if(InDegree[i] == 0)
                In ++;
            if(OutDegree[i] == 0)
                Out ++;
        }
    
        printf("%d
    ", In);
    
        if(cnt == 1)
            printf("0
    ");
        else
            printf("%d
    ", max(In, Out));
    }
    
    
    int main()
    {
        while(scanf("%d", &n) != EOF)
        {
            Init();
            for(int i=1; i<=n; i++)
            {
                int a;
                while(scanf("%d",&a), a)
                    G[i].push_back(a);
            }
    
            solve();
        }
        return0;
    }

     

  • 相关阅读:
    Codeforces 451A Game With Sticks
    POJ 3624 Charm Bracelet
    POJ 2127 Greatest Common Increasing Subsequence
    POJ 1458 Common Subsequence
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1698
    HDU 1754
    POJ 1724
    POJ 1201
    CSUOJ 1256
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4718700.html
Copyright © 2011-2022 走看看