[Noip2015] 信息传递

本文介绍了一种使用强连通分量解决特定问题的方法。该问题是关于人们通过互相告知生日来得知自己的生日,目标是最小化所需轮次。通过构建图并找到最小的强连通分量来确定最少的传播轮次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我知道这道题有多种解法,甚至暴力都可以满分,但是我在这里要介绍强连通分量的解法。

这题的题意太简单了,就是说每个人把自己的生日告诉别人,知道从别人的嘴里知道自己的生日。

很显然,一共进行的轮数就是最小的强连通分量的元素个数,因为如果形成了一个强连通分量,每个点都是可以相互到达的,所以结束肯定就是最早听到自己生日的那一次。

所以我们要求元素最小的那个强连通分量

代码:

#include<algorithm>
#include<cstdio>
using namespace std;
int son[200001],n,m,ans=999999999,group,low[200001],dfn[200001],st[200001],tot,now[200010],used[200001],popp[200001],a[200010],b[200010];
void add(int x,int y)
{
    tot++;
    now[tot]=son[x];
    son[x]=tot;
}
int top,sum,cnt,totle;
void dfs(int deep)
{
    st[++top]=deep;
    dfn[deep]=++cnt;
    low[deep]=dfn[deep];
    int nnow=top;
    for(int i=son[deep];i;i=now[i])
        if(!used[b[i]])
        {
            if(!dfn[b[i]])
                dfs(b[i]);
            low[deep]=min(low[b[i]],low[deep]);
        }
    if(dfn[deep]==low[deep])
    {
        totle++;
        if(top-nnow)ans=min(top-nnow+1,ans);
        for(int i=nnow;i<=top;i++)
            used[st[i]]=totle;
        top=nnow-1;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]),add(i,b[i]);
    for(int i=1;i<=n;i++)
        if(!used[i])dfs(i);
    printf("%d",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值