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;
}

 

原文地址:https://www.cnblogs.com/chenchengxun/p/4718700.html