题目描述
消息单向传递,求最少给多少人使得所有人都知道消息。
思路
显然对于强连通分量中的点可互相到达,无需考虑,我们缩点之后,对于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); }