#Tarjan,拓扑排序#洛谷 3436 [POI2006]PRO-Professor Szu

题目


分析

考虑有向图缩点然后拓扑排序,
最恶心的地方是这题有自环,
一旦存在自环就意味着答案一定超过阈值
其实更难过的是Tarjan大小写写错没有发现qwq


代码

#include <cstdio>
#include <cctype>
#include <stack>
#include <queue>
#define rr register
using namespace std;
const int N=1000011;
stack<int>stac; queue<int>q;
struct node{int y,next;}e[N],E[N];
int dfn[N],low[N],v[N],col[N],siz[N],m,ans,Ans;
int deg[N],n,et,Et,cnt,tot,as[N],hs[N],dp[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed min(int a,int b){return a<b?a:b;}
inline void tarjan(int x){
	dfn[x]=low[x]=++tot,
	v[x]=1,stac.push(x);
	for (rr int i=hs[x];i;i=E[i].next)
	if (!dfn[E[i].y]){
		tarjan(E[i].y);
		low[x]=min(low[x],low[E[i].y]); 
	}else if (v[E[i].y])
	    low[x]=min(low[x],dfn[E[i].y]);
	if (dfn[x]==low[x]){
		rr int y; ++cnt;
		do{
			y=stac.top(); stac.pop();
			col[y]=cnt,++siz[cnt],v[y]=0;
		}while (x^y);
	}
}
signed main(){
	n=iut()+1,m=iut();
	for (rr int i=1;i<=m;++i){
		rr int y=iut(),x=iut();
		E[++Et]=(node){y,hs[x]},hs[x]=Et;
	}
	for (rr int i=1;i<=n;++i)
	    if (!dfn[i]) tarjan(i);
	for (rr int i=1;i<=n;++i)
	for (rr int j=hs[i];j;j=E[j].next)
	if (i==E[j].y) ++siz[col[i]];
	else if (col[i]^col[E[j].y]){
		e[++et]=(node){col[E[j].y],as[col[i]]},
		as[col[i]]=et,++deg[col[E[j].y]];
	}
	for (rr int i=1;i<=cnt;++i)
	    if (!deg[i]) q.push(i);
	dp[col[n]]=1,v[col[n]]=1;
	while (!q.empty()){
		rr int x=q.front(); q.pop();
		for (rr int i=as[x];i;i=e[i].next){
			if (!(--deg[e[i].y])) q.push(e[i].y);
			if (v[x]) v[e[i].y]=1; dp[e[i].y]+=dp[x];
			if (siz[e[i].y]>1&&v[e[i].y]) dp[e[i].y]=36501;
			if (dp[e[i].y]>36501) dp[e[i].y]=36501;
		}
	}
	for (rr int i=1;i<=cnt;++i)
	    if (v[i]&&ans<dp[i]) ans=dp[i];
	if (ans==36501) printf("zawsze
");
	    else printf("%d
",ans);
	for (rr int i=1;i<=n;++i)
	    if (v[col[i]]&&ans==dp[col[i]]) ++Ans;
	printf("%d
",Ans);
	for (rr int i=1;i<=n;++i)
	    if (v[col[i]]&&ans==dp[col[i]])
		    printf("%d ",i);
	return 0;
} 
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13928646.html