2019ccpc秦皇島 Forest Program(dfs+並查集)

傳送門

題意:給一個n個點m條邊的圖,沒有重邊和自環,並且每條邊最多被一個環覆蓋,問把這個圖變成森林,即 每個聯通塊都沒有環 的圖,有多少種方案。



思路:必須去掉的邊是每個環中的某一條邊,剩下的散邊都是可以去掉,也可以不去掉,假如有k個環,每個環裏面的邊數是mi(1<=i<=k),那麼答案就是
(2m1 -1) * (2m2 -1) * (2m3-1) * … * ( 2mk-1) * 2m0
其中,m0=m-m1-m2…-mk,即所有不在環中的邊數和



剛開始不知道怎麼求一個環裏面有多少條邊,,,聽說別人都是樹剖,LCA,然鵝我也不會,就學了一個dfs暴力大法,但是因爲是無向圖,所以我們得避免同一條邊走兩次的情況,所以要單另設一個數組來標記這條邊是否已經走過。

代碼

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int M = 5e5+10, N= 3e5+10,mod = 998244353;
int e[M<<1],ne[M<<1],h[M<<1],w[M<<1],idx,cnt;
int vise[M],visv[N],pre[N],num[N],vis[N],ans[N];
int n,m;
void init()
{
	memset(h,-1,sizeof h);
	memset(num,0,sizeof num);
	memset(vis,0,sizeof vis);
	for(int i=1;i<=n;i++) pre[i]=i;
	idx=0;
}
void add(int a,int b,int c)
{
	e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
ll q_pow(ll a,int b)
{
	ll ans=1;
	while(b)
	{
		if(b&1) ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
int find(int x)
{
	if(x==pre[x]) return x;
	return pre[x]=find(pre[x]);
}
void dfs(int x,int nume)  //x-當前結點編號,nume-當前共訪問了多少條邊
{
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i],id=w[i];
		if(vise[id]) continue;  //如果這條邊已經訪問過了
		vise[id]=1;
		//如果當前結點已經訪問過了,那麼存在一個環,環中邊數爲當前總邊數-第一次走到該點時的邊數
		if(visv[j]>=0)   
			ans[cnt++]=nume-visv[j];
		else
		{
			visv[j]=nume;
			dfs(j,nume+1);
		}
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		init();
		for(int i=1;i<=m;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			add(a,b,i);add(b,a,i);
			int fa=find(a),fb=find(b);
			if(fa!=fb) num[fa]+=num[fb]+1,pre[fb]=fa;  //num數組記錄聯通塊邊數
			else num[fa]++;
		}
		ll res=1;
		for(int i=1;i<=n;i++)
		{
			int fi=find(i);
			if(!vis[fi])  //當前聯通塊沒訪問過
			{
				vis[fi]=1;
				cnt=0;
				memset(vise,0,sizeof vise);
				memset(visv,-1,sizeof visv);
				visv[fi]=0;
				dfs(fi,1);
				for(int j=0;j<cnt;j++)
				{
					res=res*(q_pow(2,ans[j])-1)%mod;
					num[fi]-=ans[j];
				}
				res=res*q_pow(2,num[fi])%mod;
			}
		}
		cout<<res<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章