给出n个点m条边的有向图,问至少添加多少条边使得任何点都可以从s点出发可达
#include<bits/stdc++.h> #define forn(i, n) for (int i = 0 ; i < int(n) ; i++) #define fore(i, s, t) for (int i = s ; i < (int)t ; i++) #define fi first #define se second #define all(x) x.begin(),x.end() #define pf2(x,y) printf("%d %d\n",x,y) #define pf(x) printf("%d\n",x) #define each(x) for(auto it:x) cout<<it<<endl; #define pi pair<int,int> using namespace std; typedef long long ll; const int maxn=1e6+5; const int maxm=2e5+5; const int inf=1e9; int head[maxn],ver[maxm],nex[maxm],tot; void inline AddEdge(int x,int y){ ver[++tot]=y,nex[tot]=head[x],head[x]=tot; } int dfn[maxn],low[maxn],num,sccnum,scc[maxn],s[maxn],d[maxn],top; void Tarjan(int x){ low[x]=dfn[x]=++num; s[++top]=x; for(int i=head[x];i;i=nex[i]){ int y=ver[i]; if(!dfn[y]) { Tarjan(y); low[x]=min(low[x],low[y]); } else if(!scc[y]) low[x]=min(low[x],dfn[y]);//说明找到了一条反祖边 } if(low[x]==dfn[x]) { sccnum++; while(s[top]!=x) { scc[s[top]]=sccnum; top--; } scc[s[top]]=sccnum; top--; } } int main(){ int n,m,s; cin>>n>>m>>s; for(int i=0;i<m;i++){ int x,y; scanf("%d%d",&x,&y); AddEdge(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i); for(int x=1;x<=n;x++){ for(int i=head[x];i;i=nex[i]){ int y=ver[i]; if(scc[x]!=scc[y]){ d[scc[y]]++; } } } int ans=0; for(int i=1;i<=sccnum;i++) if(!d[i] && i!=scc[s]) ans++; cout<<ans<<endl; }