消息的传递

https://loj.ac/problem/10094

题目描述

  消息单向传递,求最少给多少人使得所有人都知道消息。

思路

  显然对于强连通分量中的点可互相到达,无需考虑,我们缩点之后,对于DAG,只要将消息传给入度为0的人即可,其他人必定可以通过渠道得到消息。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1100,M=1e6+10;

struct Edge
{
    int x,y;
}e[M];

int nxt[M],head[N],to[M],tot;
void add_edge(int x,int y)
{
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
    e[tot].x=x;e[tot].y=y;
}

int read()
{
    int res=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+ch-'0';ch=getchar();}
    return res*w;
}
int dfn[N],low[N],st[N],top,col,co[N],idx;
void tarjan(int u)
{
    dfn[u]=low[u]=++idx;
    st[++top]=u;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!co[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        co[u]=++col;
        while(st[top]!=u)
        {
            co[st[top]]=col;
            --top;
        }
        --top;
    }
}
int in[N];
int main() 
{
    int n=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            int x=read();
            if(x==1)add_edge(i,j);
        }
    for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
    for(int i=1;i<=tot;i++)
    {
        int u=co[e[i].x],v=co[e[i].y];
        if(u!=v)
            in[v]++;
    }
    int ans=0;
    for(int i=1;i<=col;i++)
        if(!in[i])ans++;
    printf("%d",ans);
}

猜你喜欢

转载自www.cnblogs.com/fangbozhen/p/11728447.html