Tarjan(强连通分量缩点) - Network of Schools - POJ 1236

Tarjan(强连通分量缩点) - Network of Schools - POJ 1236

一些学校连接在一个计算机网络上,学校之间存在软件支援协议,每个学校都有它应支援的学校名单(学校A支援学校B,并不表示学校B一定要支援学校A)。

当某校获得一个新软件时,无论是直接获得还是通过网络获得,该校都应立即将这个软件通过网络传送给它应支援的学校。

因此,一个新软件若想让所有学校都能使用,只需将其提供给一些学校即可。

现在请问最少需要将一个新软件直接提供给多少个学校,才能使软件能够通过网络被传送到所有学校?

最少需要添加几条新的支援关系,使得将一个新软件提供给任何一个学校,其他所有学校就都可以通过网络获得该软件?

输入格式

第1行包含整数N,表示学校数量。

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

输出格式

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

数据范围

2 ≤ N ≤ 100 2≤N≤100 2N100

输入样例:

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

输出样例:

1
2

分析:

分 析 题 意 : 分析题意:

第 一 问 : 至 少 从 几 个 点 出 发 , 能 够 遍 历 图 中 所 有 点 。 第一问:至少从几个点出发,能够遍历图中所有点。

第 二 问 : 至 少 添 加 几 条 边 , 能 够 使 整 个 图 变 成 强 连 通 图 。 第二问:至少添加几条边,能够使整个图变成强连通图。 使

我 们 首 先 通 过 t a r j a n 算 法 进 行 缩 点 , 得 到 一 个 拓 扑 图 。 我们首先通过tarjan算法进行缩点,得到一个拓扑图。 tarjan

接 着 统 计 拓 扑 图 内 , 每 个 强 连 通 分 量 的 出 度 和 入 度 。 接着统计拓扑图内,每个强连通分量的出度和入度。

因 为 每 个 强 连 通 分 量 内 部 的 点 都 是 相 互 连 通 的 , 因为每个强连通分量内部的点都是相互连通的,

所 以 要 想 遍 历 图 中 所 有 点 , 我 们 至 少 要 从 拓 扑 图 中 的 所 有 起 点 出 发 。 所以要想遍历图中所有点,我们至少要从拓扑图中的所有起点出发。

拓 扑 图 中 起 点 的 数 量 即 强 连 通 分 量 入 度 为 零 的 点 的 数 量 P 。 拓扑图中起点的数量即强连通分量入度为零的点的数量P。 P

因 此 第 一 问 的 答 案 为 P 。 因此第一问的答案为P。 P

对 于 第 二 问 , 假 设 出 度 为 0 的 强 连 通 分 量 数 量 为 Q , 结 论 : m a x ( P , Q ) 。 对于第二问,假设出度为0的强连通分量数量为Q,结论:max(P,Q)。 0Qmax(P,Q)

证明:

拓 扑 图 中 , 起 点 和 终 点 的 对 称 的 , 故 我 们 假 设 P ≤ Q 。 拓扑图中,起点和终点的对称的,故我们假设P≤Q。 PQ

① 、 当 P = 1 时 , 在 所 有 终 点 到 起 点 之 间 均 连 接 一 条 有 向 边 , 即 可 形 成 强 连 通 图 , 共 需 要 增 加 Q 条 有 向 边 。 ①、当P=1时,在所有终点到起点之间均连接一条有向边,即可形成强连通图,共需要增加Q条有向边。 P=1Q

② 、 当 P > 1 时 , ②、当P>1时, P>1

任 选 两 条 起 点 和 终 点 不 同 的 路 线 : P 1 − > Q 1 和 P 2 − > Q 2 。 任选两条起点和终点不同的路线:P_1->Q_1和P_2->Q_2。 线:P1>Q1P2>Q2

我 们 在 Q 2 与 P 1 之 间 连 接 一 条 有 向 边 , 则 这 两 条 路 线 即 可 视 作 一 条 路 线 : P 2 − > Q 1 。 我们在Q_2与P_1之间连接一条有向边,则这两条路线即可视作一条路线:P_2->Q_1。 Q2P1线线P2>Q1

重 复 上 述 操 作 P − 1 次 , 起 点 仅 剩 下 1 个 , 终 点 剩 下 Q − ( P − 1 ) 个 。 重复上述操作P-1次,起点仅剩下1个,终点剩下Q-(P-1)个。 P11Q(P1)

P = 1 时 , 我 们 需 要 增 加 的 边 的 数 量 等 于 终 点 的 数 量 , 等 于 Q − ( P − 1 ) 个 。 P=1时,我们需要增加的边的数量等于终点的数量,等于Q-(P-1)个。 P=1Q(P1)

故 总 共 我 们 需 要 新 增 P − 1 + Q − ( P − 1 ) = Q 条 边 。 故总共我们需要新增P-1+Q-(P-1)=Q条边。 P1+Q(P1)=Q

故 第 二 问 的 结 论 为 m a x ( P , Q ) 。 故第二问的结论为max(P,Q)。 max(P,Q)

注意:

对 于 第 二 问 , 若 强 连 通 分 量 仅 有 1 个 , 即 原 图 本 身 就 是 强 连 通 图 , 特 判 输 出 0 。 对于第二问,若强连通分量仅有1个,即原图本身就是强连通图,特判输出0。 10

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=110, M=10010;

int n;
int e[M],ne[M],h[N],idx;
int stk[N],top;
bool in_stk[N];
int din[N],dout[N];
int id[N],ssc_cnt;
int dfn[N],low[N],timestamp;

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void tarjan(int u)
{
    dfn[u]=low[u]=++timestamp;
    stk[++top]=u,in_stk[u]=true;
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(!dfn[j])
        {
            tarjan(j);
            low[u]=min(low[u],low[j]);
        }
        else if(in_stk[j]) low[u]=min(low[u],dfn[j]);
    }

    if(dfn[u]==low[u])
    {
        ++ssc_cnt;
        int y;
        do
        {
            y=stk[top--];
            in_stk[y]=false;
            id[y]=ssc_cnt;
        }while(y!=u);
    }
}

int main()
{
    cin>>n;
    
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++)
    {
        int t;
        while(cin>>t,t) add(i,t);
    }
    
    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;j=ne[j])
        {
            int k=e[j];
            int a=id[i],b=id[k];
            if(a!=b) din[b]++,dout[a]++;
        }
        
    int P=0,Q=0;
    for(int i=1;i<=ssc_cnt;i++) //缩点后,图中只有ssc_cnt个点
    {
        if(!din[i]) P++;
        if(!dout[i]) Q++;
    }

    printf("%d\n",P);
    if(ssc_cnt==1) puts("0");
    else printf("%d\n",max(P,Q));
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值