最大半联通子图

RT,调了一年

思路大概两个月前就有所了解,一直口胡没写

注意新图要去重边,一个很好的写法是把可以建的边按字典序排序,跟上一个比较

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>

inline int max(int x,int y){return x>y?x:y;}

inline int min(int x,int y){return x<y?x:y;}

int n,m,MOD,cnt,Cnt,Ant,maxi,tarclock,colorclock,head[100005],
	Head[100005],dfn[100005],low[100005],dep[100005],
	size[100005],ind[100005],color[100005],f[100005],vis[100005];
	
std::queue<int> q;

std::stack<int> s;

struct edge{
	int v,next;
}e[1000005];

inline void add(int u,int v){
	e[++cnt].v=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}

struct Edge{
	int v,next;
}E[1000005];

inline void Add(int u,int v){
	E[++Cnt].v=v;
	E[Cnt].next=Head[u];
	Head[u]=Cnt;
}

struct arr{
	int u,v;
}A[1000005];

inline bool cmp(arr x,arr y){
	if(x.u!=y.u)return x.u<y.u;
	return x.v<y.v;
}

inline void tarjan(int u){
	dfn[u]=low[u]=++tarclock;
	vis[u]=1;
	s.push(u);
	for(int i=head[u];i!=-1;i=e[i].next){
		int v=e[i].v;
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v])low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u]){
		colorclock++;
		while(1){
			int x=s.top();
			s.pop();
			vis[x]=0;
			color[x]=colorclock;
			size[colorclock]++;
	//		printf("%d in %d
",x,colorclock);
			if(x==u)break;
		}
	}
}

inline void Rebuild(){
	for(int u=1;u<=n;u++){
		for(int i=head[u];i!=-1;i=e[i].next){
			int v=e[i].v;
			if(color[u]!=color[v]){
				A[++Ant].u=color[u];
				A[Ant].v=color[v];
			}
		}
	}
	std::sort(A+1,A+Ant+1,cmp);
	for(int i=1;i<=Ant;i++){
		if(A[i-1].u==A[i].u&&A[i-1].v==A[i].v)continue;
		ind[A[i].v]++;
		Add(A[i].u,A[i].v);
	}
//	for(int u=1;u<=n;u++){
	//	printf("the ind of %d is %d
",u,ind[u]);
//	}
}

inline void topo(){
	for(int u=1;u<=colorclock;u++){
		if(!ind[u]){
			q.push(u);
			f[u]=1;
			dep[u]=size[u];
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		maxi=max(maxi,dep[u]);
		for(int i=Head[u];i!=-1;i=E[i].next){
			int v=E[i].v;
			if(dep[v]<dep[u]+size[v]){
		//		printf("%d is updated by %d
",v,u);
				dep[v]=dep[u]+size[v];
				f[v]=f[u]%MOD;
			}
			else if(dep[v]==dep[u]+size[v]){
				f[v]=(f[v]+f[u])%MOD;
			}
			ind[v]--;
			if(!ind[v]){
				q.push(v);
			}
		}
	}
}

inline void getans(){
	int ans=0;
	for(int i=1;i<=colorclock;i++){
		if(dep[i]==maxi){
			ans+=f[i];
			ans%=MOD;
		}
	}
//	for(int i=1;i<=colorclock;i++){
//		printf("%d:dep=%d f=%d
",i,dep[i],f[i]);
//	}
	printf("%d
%d
",maxi,ans);
}

int main(){
	memset(head,-1,sizeof(head));
	memset(Head,-1,sizeof(Head));
	scanf("%d%d%d",&n,&m,&MOD);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i])tarjan(i);
	}
	Rebuild();
	topo();
	getans();
}
原文地址:https://www.cnblogs.com/Y15BeTa/p/11674093.html