zoukankan      html  css  js  c++  java
  • VijosP1595:学校网络(有向图变强连通图)

    描述

    一些学校的校园网连接在一个计算机网络上。学校之间存在软件支援协议。每个学校都有它应支援的学校名单(学校a支援学校b,并不表示学校b一定支援学校a)。当某校获得一个新软件时,无论是直接得到的还是从网络得到的,该校都应立即将这个软件通过网络传送给它应支援的学校。因此,若需要让所有连接在网络上的学校都能使用一个新软件,只需要将其提供给其中一些学校即可。

    子任务a:根据学校间软件支援协议(各个学校的支援名单),计算最少需要将一个软件直接提供给多少个学校,才能使该软件通过网络传送到所有学校。

    子任务b:如果允许在原有支援协议上添加新的支援关系,则总可以形成一个新的协议,使得此时只需要将一个新软件提供给任何一个学校,其他所有学校就都可以通过网络获得该软件。请计算出最少需要添加几条新的支援关系。

    输入格式

    第一行是一个整数 n(2≤n≤100),表示与网络连接的学校总数。接下来 n行描述了每个学校要支援的学校。第i+1行表示第i 号学校要支援的所有学校的编号,编号之间用空格隔开,每行以数字0 结束。如果某个学校不支援任何学校,则相应的行会有一个0。

    输入:

    5
    2 4 3 0
    4 5 0
    0
    0
    1 0

    输出

    1

    2

    定理:使图变为双连通的所添加的无向边数目为:(缩点后的图的叶子结点数+1)/2;

    使有向图变为强连通的所添加的有向边数目为:缩点后 max(入度为0的结点数目,出度为0的结点数目);

    思路:任务a即哪些点开始遍历可将图中的结点遍历完毕,求这些点的最小数目。任务b即最少添加多少条边可使有向图变为一个强连通图。将有向图缩点后任务a即为入度为0的连通分量,任务b为入度为0的连通分量数目与出度为0的连通分量数目较大的一个,若只有一个连通分量直接输出1,0。

    PS:当结点数目较少时用邻接矩阵表示图,防止存在重边。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int MAXN=105;
    int mp[MAXN][MAXN];
    int n;
    int dfn[MAXN],low[MAXN],index;
    int stack[MAXN],top;
    bool ins[MAXN];
    int belong[MAXN],cnt;
    
    void tarjan(int u)
    {
        dfn[u]=low[u]=++index;
        stack[top++]=u;
        ins[u]=true;
        for(int v=1;v<=n;v++)
        {
            if(mp[u][v])
            {
                if(!dfn[v])
                {
                    tarjan(v);
                    low[u]=min(low[u],low[v]);
                }
                else if(ins[v]) low[u]=min(low[u],dfn[v]);
            }
        }
        if(low[u]==dfn[u])
        {
            int v;
            ++cnt;
            do{
                v=stack[--top];
                ins[v]=false;
                belong[v]=cnt;
            }while(u!=v);
        }
    }
    int indeg[MAXN];
    int outdeg[MAXN];
    void solve()
    {
        for(int i=1;i<=n;i++)
        {
            for(int v=1;v<=n;v++)
            {
                if(mp[i][v])
                {
                    if(belong[i]!=belong[v])
                    {
                        indeg[belong[v]]++;
                        outdeg[belong[i]]++;
                    }
                }
            }
        }
        int in=0,out=0;
        for(int i=1;i<=cnt;i++)
        {
            if(indeg[i]==0)
                in++;
            if(outdeg[i]==0)
                out++;
        }
        if(cnt!=1)    
            printf("%d
    %d
    ",in,max(in,out));
        else
            printf("%d
    %d
    ",1,0);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int v;
            do{
                scanf("%d",&v);
                if(v==0)    break;
                else    mp[i][v]=1;
            }while(true);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        solve();
        return 0;
    }
  • 相关阅读:
    Jmeter学习笔记-初级
    python selenium利用 126.com id自动生成
    Python代码无法保存
    卸载python2.7出错
    python pip用法
    pycharm 连接数据库
    Python打包PyPI上传实践
    Python实现Api的Mock测试
    抓包工具使用
    Jenkins+Ant可持续集成Jmeter脚本
  • 原文地址:https://www.cnblogs.com/program-ccc/p/5384085.html
Copyright © 2011-2022 走看看