P2272 [ZJOI2007] 最大半连通子图 解题报告

题意

在有向图 \(G\) 中找出节点数最多的半连通导出子图(称为最大半连通子图),并输出其节点数 \(K\) 以及不同最大半连通子图的个数 \(C\)

半连通的定义:对于图中任意两点 \(u\),\(v\),至少存在一条从 \(u\)\(v\) 或从 \(v\)\(u\) 的有向路径。

思路

这个性质等价于将原图缩点后得到的 DAG必须是一条链(即任意两点之间都有路径)。

因为如果 DAG 中存在分叉(例如两个不同分支没有相互可达路径),那么这两个分支中的点就不满足半连通条件。

因此,最大半连通子图对应于缩点后 DAG 上的一条最长路径

且该路径上的所有分量必须全部选取,因为选取部分分量会破坏半连通性,且加入剩余点不会破坏半连通性。

不同的最大半连通子图对应不同的最长路径。

注意事项

  1. 要处理重边,不同边的统计会导致同一个最长路径被重复计数多次。

代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f
#define int long long
const int N=1e5+10;
map<pair<int,int>,bool>num;
int n,m,low[N],dfn[N],vis[N],a[N],b[N],dp1[N],s[N],t,cnt,sum[N],ans1;
long long dp2[N],ans2,mod;
vector<int>q[N],p[N];

void dfs(int x)
{
	dfn[x]=low[x]=++t;
	s[t]=x;
	for(int i=0;i<q[x].size();i++)
	{
		int v=q[x][i];
		if(!dfn[v])
		{
			dfs(v);
			low[x]=min(low[x],low[v]);
		}
		else if(!vis[v]) // 在栈中
		{
			low[x]=min(low[x],dfn[v]);
		}
	}
	if(dfn[x]==low[x])
	{
		cnt++;
		while(s[t]!=x)
		{
			vis[s[t]]=cnt;
			sum[cnt]++;
			t--;
		}
		vis[x]=cnt;
		sum[cnt]++;
		t--;
	}
}

signed main()
{
	cin>>n>>m>>mod;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		q[x].push_back(y);
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i] && !vis[i])
			dfs(i);
	t=0;
	for(int i=1;i<=n;i++)
		for(int j=0;j<q[i].size();j++)
			if(vis[i]!=vis[q[i][j]] && !num[make_pair(vis[i],vis[q[i][j]])])
			{
				p[vis[i]].push_back(vis[q[i][j]]);
				b[vis[q[i][j]]]++;
				num[make_pair(vis[i],vis[q[i][j]])]=1;
			}
	for(int i=1;i<=cnt;i++)
	{
		if(b[i]==0)
			a[++t]=i;
		dp2[i]=1;
	}
	for(int i=1;i<=t;i++)
	{
		sum[a[i]]+=dp1[a[i]];
		ans1=max(ans1,sum[a[i]]);
		for(int j=0;j<p[a[i]].size();j++)
		{
			int v=p[a[i]][j];
			b[v]--;
			if(b[v]==0)
				a[++t]=v;
			if(sum[a[i]]==dp1[v])
				dp2[v]=(dp2[v]+dp2[a[i]])%mod;
			if(sum[a[i]]>dp1[v])
			{
				dp2[v]=dp2[a[i]];
				dp1[v]=sum[a[i]];
			}
		}
	}
	for(int i=1;i<=cnt;i++)
	{
		if(sum[i]==ans1)
			ans2=(ans2+dp2[i])%mod;
		if(sum[i]>ans1)
		{
			ans2=dp2[i];
			ans1=sum[i];
		}
	}
	cout<<ans1<<"\n"<<ans2%mod;
	return 0;
}
posted @ 2026-06-06 13:12  Luowj  阅读(13)  评论(0)    收藏  举报