洛谷2002 消息扩散
题目描述
有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息。
输入格式:
第一行两个整数n,m表示n个城市,m条单向道路。
以下m行,每行两个整数b,e表示有一条从b到e的道路,道路可以重复或存在自环。
输出格式:
一行一个整数,表示至少要在几个城市中发布消息。
tarjan缩点以后求出入度为0的点就可以了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define maxn 100005 #define maxm 500005 using namespace std; int n,m,cnt,head[maxn],x[maxm],y[maxm],du[maxn]; int dfn[maxn],low[maxn],vis[maxn],bel[maxn],q[maxn]; struct edge{ int next,to; }e[maxm]; void insert(int u,int v){ cnt++; e[cnt].next=head[u];e[cnt].to=v; head[u]=cnt; } int top,ind,k; void tarjan(int x){ q[++top]=x; dfn[x]=low[x]=++ind; vis[x]=1; for(int i=head[x];i;i=e[i].next){ int s=e[i].to; if(!dfn[s]){ tarjan(s); low[x]=min(low[s],low[x]); } else if(vis[s]){ low[x]=min(dfn[s],low[x]); } } int now=0; if(dfn[x]==low[x]){ k++; while(now!=x){ now=q[top];top--; vis[now]=0; bel[now]=k; } } } int ans; void work(){ for(int i=1;i<=k;i++){ if(!du[i]){ ans++; } } } int mx=0; int main(){ scanf("%d%d",&n,&m); int u,v,t; for(int i=1;i<=m;i++){ scanf("%d%d",&x[i],&y[i]); insert(x[i],y[i]); } for(int i=1;i<=n;i++){ if(!dfn[i])tarjan(i); } cnt=0; memset(head,0,sizeof head); memset(e,0,sizeof e); for(int i=1;i<=m;i++){ if(bel[x[i]]!=bel[y[i]]){ insert(bel[x[i]],bel[y[i]]); du[bel[y[i]]]++; } } work(); printf("%d",ans); return 0; }