luogu P2272 [ZJOI2007]最大半连通子图

代码:

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

using namespace std;

const int N=1000009;
stack <int> s;
queue <int> q;
int head[N],cnt,SCC,n,m,M,x[N*10],y[N*10],siz[N],tmp=0;
int belong[N],LOW[N],DFN[N],deg[N],Index,ins[N],num[10*N],f[N],gg[N];
struct Edge
{
	int nxt,to;
}g[N*10];

void add(int from,int to)
{
	g[++cnt].nxt=head[from];
	g[cnt].to=to;
	head[from]=cnt;
}

int read()
{
	int x=0;
	char c=getchar();
	while(c<'0'||c>'9')
		c=getchar();
	while(c>='0'&&c<='9')
		x=x*10+c-'0',c=getchar();
	return x;
}

void init()
{
	n=read(),m=read(),M=read();
//	for (int i=1;i<=100000;i++)
//		printf("%d\n",siz[i]);
	for (int i=1;i<=m;i++)
	{
		x[i]=read(),y[i]=read();
		add(x[i],y[i]);
	}	
}

void Tarjan(int x)
{
	DFN[x]=LOW[x]=++Index;
	s.push(x);ins[x]=1;
	for (int i=head[x];i;i=g[i].nxt)
	{
		int v=g[i].to;
		if(!DFN[v])
		{
			Tarjan(v);
			LOW[x]=min(LOW[x],LOW[v]);
		}
		else if(ins[v])
			LOW[x]=min(LOW[x],DFN[v]);
	}
	if(DFN[x]==LOW[x])
	{
		int v;SCC++;
		do
		{
			v=s.top(),belong[v]=SCC,ins[v]=0;
			siz[SCC]++;
			s.pop();
		}while(v!=x);
	}
}

bool cmp(int a,int b)
{
	if(x[a]==x[b])
		return y[a]<y[b];
	return x[a]<x[b];
}

void TP_sort()
{
	for (int i=1;i<=SCC;i++)
		if(deg[i]==0)
			q.push(i),f[i]=siz[i],gg[i]=1;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for (int i=head[x];i;i=g[i].nxt)
		{
			int v=g[i].to;
			if(siz[v]+f[x]>f[v])
				f[v]=siz[v]+f[x],gg[v]=gg[x];
			else if(siz[v]+f[x]==f[v])
				gg[v]=(gg[v]+gg[x])%M;
			if(!--deg[v])
				q.push(v);
		}
	}
}

void work()
{
//	memset(siz,0,sizeof(siz));
	for (int i=1;i<=n;i++)
		if(!DFN[i])
			Tarjan(i);
	int sum=0;
	for (int i=1;i<=SCC;i++)
		sum+=siz[i];
	for (int i=1;i<=m;i++)
		num[i]=i,x[i]=belong[x[i]],y[i]=belong[y[i]];
	sort(num+1,num+1+m,cmp);
	memset(head,0,sizeof(head));
	for (int i=1;i<=m;i++)
		if(x[num[i]]!=y[num[i]]&&(x[num[i]]!=x[num[i-1]]||y[num[i]]!=y[num[i-1]]))
			add(x[num[i]],y[num[i]]),deg[y[num[i]]]++;
	TP_sort();
	int Max=0;
	for (int i=1;i<=SCC;i++)
		Max=max(Max,f[i]);
	int ans=0;
	for (int i=1;i<=SCC;i++)
		ans=(ans+(Max==f[i]?gg[i]:0))%M;
	printf("%d\n%d\n",Max,ans);
}

int main()
{
	init();
	work();
	return 0;
}
posted @ 2020-05-08 20:43  With_penguin  阅读(113)  评论(0编辑  收藏  举报