ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

学校网络

2022-07-25 20:04:48  阅读:155  来源: 互联网

标签:int 网络 学校 dfn low 软件 分量


学校网络

题目描述:

一些学校连接在一个计算机网络上,学校之间存在软件支援协议,每个学校都有它应支援的学校名单(学校 A 支援学校 B,并不表示学校 B 一定要支援学校 A)。当某校获得一个新软件时,无论是直接获得还是通过网络获得,该校都应立即将这个软件通过网络传送给它应支援的学校。因此,一个新软件若想让所有学校都能使用,只需将其提供给一些学校即可。现在请问最少需要将一个新软件直接提供给多少个学校,才能使软件能够通过网络被传送到所有学校?最少需要添加几条新的支援关系,使得将一个新软件提供给任何一个学校,其他所有学校就都可以通过网络获得该软件?

输入格式

第 1 行包含整数 N,表示学校数量。
第 2…N+1 行,每行包含一个或多个整数,第 i+1 行表示学校 i 应该支援的学校名单,每行最后都有一个 0 表示名单结束(只有一个 0 即表示该学校没有需要支援的学校)。

输出格式

输出两个问题的结果,每个结果占一行。

数据范围

2≤N≤100

输入样例:

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

输出样例:

1
2

思路

Tarjan模板题,Tarjan缩点将原图转化成 DAG(有向无环图),统计每个强连通分量的出度入度,记录起点数量,终点数量。对于一个强连通分量,其中只要有一所学校获得新软件那么整个分量都能获得。所以只要把软件给所有起点即可,答案为起点个数 。对于第二个问题,如果只有一个强连通分量,那么答案为0,因为全在一个强连通分量中,不需要填边就能随意传输,如果强连通分量大于1,最后答案为max(出度为0的数量,入度为0的数量)。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=110,M=100010;
int dfn[N],low[N],timetemp; //dfn[i]表示搜到i点的时间戳,low[i]表示i点能回溯到的时间戳
int h[N],e[M],ne[M],idx;  //链式前向星
int id[N];      //表示i点所在的连通分量
int din[N];     //缩点以后的入度
int dout[N];    //缩点以后的出度
int n;
stack<int> st;  
bool inst[N];  
int num;
void add(int a,int b)
{
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
void Tarjan(int u)
{
    dfn[u]=low[u]=++idx;
    st.push(u),inst[u]=true;
    for(int i=h[u];i!=-1;i=ne[i]) {
        int j=e[i];
        if(!dfn[j]) {   //如果没有被搜过
            Tarjan(j);
            low[u]=min(low[u],low[j]);
        }
        else if(inst[j]) low[u]=min(low[u],dfn[j]);  //如果被搜过了并且在栈中
     }
    if(dfn[u]==low[u]) {       //同一个连通分量的出栈
        ++num;
        int now;
        do{
            now=st.top();
            st.pop();
            inst[now]=false;
            id[now]=num;
        }while(u!=now);
    }
}
int main()
{
    memset(h,-1,sizeof(h));
    cin>>n;
    for(int i=1;i<=n;i++) {
        int x;
        while(cin>>x,x) {
            add(i,x);
        }
    }
    for(int i=1;i<=n;i++) {
        if(!dfn[i]) Tarjan(i);
    }
    for(int i=1;i<=n;i++) {              //遍历连边
        for(int j=h[i];j!=-1;j=ne[j]) {
            int k=e[j];
            int a=id[i],b=id[k];
            if(a!=b) {
                dout[a]++;
                din[b]++;
            }
        }
    }
    int a=0,b=0;
    for(int i=1;i<=num;i++) {
        if(din[i]==0) a++;
        if(dout[i]==0) b++;
    }
    cout<<a<<endl;
    if(num==1) cout<<0<<endl;
    else cout<<max(a,b)<<endl;
    // system("pause");
    return 0;
}

标签:int,网络,学校,dfn,low,软件,分量
来源: https://www.cnblogs.com/HYWdsds/p/16507913.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有