描述:https://www.luogu.com.cn/problem/P2002
有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息。
tarjan缩点
缩点以后图就变成了几张无环图
那么对于这样的图,入度为0的点就是答案
因为入度不为0的点会一直把消息传达下去
#include <iostream> #include <algorithm> #include <cstring> #include <string.h> #include <math.h> using namespace std; const int maxn=500005; int n,m,fen,belong[maxn]; struct p{ int to,nxt; }d[maxn];int cnt=1,head[maxn]; void add(int u,int v){ d[cnt].nxt=head[u],d[cnt].to=v,head[u]=cnt++; } int low[maxn],dfn[maxn],stac[maxn],vis[maxn],top,id,ru[maxn]; void tarjan(int x){ dfn[x]=low[x]=++id;vis[x]=1; stac[++top]=x;vis[x]=1; for(int i=head[x];i;i=d[i].nxt){ int y=d[i].to; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(vis[y]) low[x]=min(low[x],low[y]); } if(low[x]==dfn[x]){ fen++;//记录连通分量 int temp; while(temp=stac[top--]) { belong[temp]=fen;//记录在哪个连通分量 vis[temp]=0; if(temp==x) break; } } } int main() { int n,m; cin>>n>>m; int x,y; for(int i=1;i<=m;i++){ cin>>x>>y; add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) { for(int j=head[i];j;j=d[j].nxt) if(belong[i]!=belong[d[j].to])//处于不同的连通分量 ru[belong[d[j].to]]++; } int ans=0; for(int i=1;i<=fen;i++) if(!ru[i]) ans++; cout<<ans; return 0; }