[HAOI2006]受欢迎的牛 G-强连通分量

题目

题目
tarjan算法每次打都要翻书,于是就学了一个叫Korasaju算法的东西

程序

给定有向图,缩点,判断是不是只有一个点出度为0,是,输出,否则输出0。

#include <iostream>
#include <cstring>

using namespace std;
const int N=2E5+10,M=2E5+10;
int scc[N],sc;
int to1[M],nxt1[M],head1[M],cnt1;
int to2[M],nxt2[M],head2[M],cnt2;
int to[M],nxt[M],head[M],cnt;
bool v[N],vis[N],f;
int t[N];
int s[N],tot;
int n,m,ans;
void add(int u,int v) {
	to[++cnt]=v;
	nxt[cnt]=head[u];
	head[u]=cnt;
}
void add1(int u,int v) {
	to1[++cnt1]=v;
	nxt1[cnt1]=head1[u];
	head1[u]=cnt1;
}
void add2(int u,int v) {
	to2[++cnt2]=v;
	nxt2[cnt2]=head2[u];
	head2[u]=cnt2;
}

void dfs1(int p) {
	v[p]=true;
	for(int i=head1[p];i;i=nxt1[i]) {
		if(!v[to1[i]])
		  dfs1(to1[i]);
	}
	s[++tot]=p;
}

void dfs2(int p) {
	scc[p]=sc;
	t[sc]++;
	for(int i=head2[p];i;i=nxt2[i]) {
		if(!scc[to2[i]])
		  dfs2(to2[i]);
	}
}

void kosa() {
	for(int i=1;i<=n;i++)
	  if(!v[i])
	    dfs1(i);
	for(int i=n;i>=1;i--) {
		if(!scc[s[i]]) { 
			sc++;
		 	dfs2(s[i]);
		} 
	}
}

int main() {
	cin>>n>>m;
	while(m--) {
		int u,v;
		cin>>u>>v;
		add1(u,v);
		add2(v,u);
	}
	kosa();
	for(int i=1;i<=n;i++) {
		for(int j=head1[i];j;j=nxt1[j]) {
			int y=to1[j];
			if(scc[i]==scc[y])
			  continue;
			vis[scc[i]]=true;
			continue;
		}
	}
	for(int i=1;i<=n;i++)
	  if(!scc[i]) {
	  	cout<<0<<endl;
	  	return 0;
	  }
	for(int i=1;i<=sc;i++)
	  	if(!vis[i]) { 
	    	ans+=t[i];
	    	if(f==true) {
	    		cout<<0<<endl;
	    		return 0;
			} 
			f=true;
		} 
	cout<<ans;
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/wyc06/p/12808175.html