Codeforces-(此題題號有誤我也不知道是啥了。)

//好久沒寫博客了,最近腦子感覺非常不好使。個人認爲寫博客是提升總結的一個重要途徑,於是我又回來了。

題意要求使每條邊兩端的頂點填上的值和爲奇數,則很容易想到如果一端是奇數,則另一端只能是偶數,符合題意的構造方式必須是奇偶相間的。那麼題目轉化爲檢查題目中所給圖是否爲一個二分圖,設將頂點集V分爲的兩個集合大小分別爲cnt0,cnt1,那麼該圖的方案個數爲2^{cnt0}+2^{cnt1}。因爲可用的奇數有2個,偶數只有1個,所以大小爲cnt0的頂點集合填奇數共有2^{cnt0}種,大小爲cnt1的頂點集合填奇數共有2^{cnt1}種,相加即爲所求。檢查二分圖可以採用黑白染色的方法,如果遇到相鄰的點已被染成同一顏色即返回false。

坑點:

1.題目並未保證所給圖連通,因此需要對每個連通子圖分別計算結果,然後運用乘起來(乘法原理)

2.多測。數組,變量勿忘初始化

3.t高達3e5,如果你試圖用memset初始化數組會超時。

#include<bits/stdc++.h>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define ll long long
#define pq priority_queue
#define mp make_pair
#define pii pair<int,int>
#define mod 998244353
#define debug(x) cerr<<#x<<"="<<x<<'\n'

int lowbit(int x) {return x&(-x);}
int T;
int n,m;
vector <int> edge[300010];
int cnt0,cnt1;
ll ans;
int col[300010];
int power[300010];

bool bfs(int node,int c) {
	col[node]=c;
	if (c==0) cnt0++;
	else cnt1++;
	for (int i=0;i<edge[node].size();i++) {
		int v=edge[node][i];
		if (col[v]!=-1) {
			if (col[v]==c) return false;
		}
		else if (!bfs(v,1-c)) return false;
	}
	return true;
}

int add(int a,int b) {
	return (a+b)%mod;
}

void solve() {
	ans=1;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) edge[i].clear();
	for (int i=0;i<m;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		edge[u].pb(v);
		edge[v].pb(u);
	}
	for (int i=1;i<=n;i++) col[i]=-1;
	for (int i=1;i<=n&&ans!=0;i++) {
		cnt0=cnt1=0;
		if (col[i]!=-1) continue;
		if (!bfs(i,0)) ans=0;
		else ans=1ll*ans*add(power[cnt0],power[cnt1])%mod;
	}
	printf("%d\n",ans);
}

int main(){
	scanf("%d",&T);
	power[0]=1;
	for (int i=1;i<300010;i++) power[i]=power[i-1]*2ll%mod;
	while (T--) solve();
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章