cf999E (强联通分量模板题)

给出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; 
}

  

 

cf999E (强联通分量模板题)

上一篇:虚拟环境的基本使用 virtualenv,virtualenvwrapper


下一篇:MYSQL(一)数据库基本概念