其他分享
首页 > 其他分享> > ZJOI 2007最大半连通子图--Tarjan缩点+拓扑排序

ZJOI 2007最大半连通子图--Tarjan缩点+拓扑排序

作者:互联网

Loj 10092

在这里插入图片描述

题目分析:

Code:

#include <bits/stdc++.h>
using namespace std;
#define maxn 100010
#define maxm 1000010

int ans=0,du[maxn],d[maxn],ac[maxn],sum[maxn],n,m,mod,head[maxn],size=0,dfn[maxn],low[maxn],st[maxn],top=0,co[maxn],col=0,cnt=0;
struct edge {
	int u,v,nxt;
}e[maxm];
struct node {
	int v,nxt;
}ne[maxm];

inline void init_() {
	freopen("a.txt","r",stdin);
}

inline int read_() {
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=(x<<3)+(x<<1)+c-'0';
		c=getchar();
	}
	return x*f;
}

inline void clean_() {
	memset(head,-1,sizeof(head));
	memset(dfn,0,sizeof(dfn));
	memset(co,0,sizeof(co));
	memset(sum,0,sizeof(sum));
	memset(du,0,sizeof(du));
	memset(d,0,sizeof(d));
	memset(ac,0,sizeof(ac));
}

inline void add_(int u,int v) {
	e[++size].u=u;
	e[size].v=v;
	e[size].nxt=head[u];
	head[u]=size;
}

void Tarjan_(int u) {
	dfn[u]=low[u]=++cnt;
	st[++top]=u;
	for(int i=head[u];~i;i=e[i].nxt) {
		int v=e[i].v;
		if(!dfn[v]) {
			Tarjan_(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!co[v]) {
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]) {
		co[u]=++col;
		++sum[col];
		while(st[top]!=u) {
			co[st[top]]=col;
			++sum[col];
			--top;
		}
		--top;
	}
}

inline bool cmp_(edge aa,edge bb) {
	if(aa.u==bb.u) return aa.v<bb.v;
	else return aa.u<bb.u;
}

inline void new_add_(int u,int v) {
	ne[++size].v=v;
	ne[size].nxt=head[u];
	head[u]=size;
}

inline void rebuild_() {
	for(int i=1;i<=m;++i) {
		int u=co[e[i].u],v=co[e[i].v];
		e[i].u=u;e[i].v=v;
	}
	sort(e+1,e+m+1,cmp_);
	memset(head,-1,sizeof(head));
	size=0;
	int last_u=-1,last_v=-1;
	for(int i=1;i<=m;++i) {
		if(e[i].u==e[i].v) continue;
		if(e[i].u==last_u&&e[i].v==last_v) continue;
		new_add_(e[i].u,e[i].v);
		last_u=e[i].u;last_v=e[i].v;
		++du[e[i].v];
	}
}

inline void first_topu_() {
	top=0;
	for(int i=1;i<=col;++i) {
		if(!du[i]) {
			st[++top]=i;
			d[i]=sum[i];
			ac[i]=1;
			if(d[i]>d[ans]) ans=i;
		}
	}
}

inline void topu_() {
	int pdc=0;
	while(pdc<=top) {
		int u=st[++pdc];
		for(int i=head[u];~i;i=ne[i].nxt) {
			int v=ne[i].v;
			--du[v];
			if(d[v]<d[u]+sum[v]) {
				d[v]=d[u]+sum[v];
				ac[v]=0;
				if(d[v]>d[ans]) ans=v;
			}
			if(d[v]==d[u]+sum[v]) {
				ac[v]=(ac[u]+ac[v])%mod;
			}
			if(!du[v]) st[++top]=v;
		}
	}
}

int AK=0;
inline void ask_ac_() {
	for(int i=1;i<=col;++i) {
		if(d[ans]==d[i]) {
			AK+=ac[i]%mod;
		}
	}
}

void readda_() { 
	clean_();
	n=read_();m=read_();mod=read_();
	int x,y;
	for(int i=1;i<=m;++i) {
		x=read_();y=read_();
		add_(x,y);
	}
	for(int i=1;i<=n;++i) {
		if(!dfn[i]) Tarjan_(i);
	}
	rebuild_();
	first_topu_();
	topu_();
	ask_ac_();	
	printf("%d\n%d",d[ans],AK%mod);
}

int main() {
	init_();
	readda_();
	return 0;
}

标签:缩点,ac,ZJOI,int,void,子图,maxn,ans,inline
来源: https://blog.csdn.net/weixin_44574520/article/details/97619229