1. 程式人生 > 實用技巧 >Beautiful Graph CodeForces - 1093D 二分圖判定 簡單組合

Beautiful Graph CodeForces - 1093D 二分圖判定 簡單組合

Beautiful Graph CodeForces - 1093D 二分圖判定 簡單組合

題意

給定一張\(n\)個點\(m\)條邊的無向圖,可以給每個點賦值\(1,2,3\)

要求賦值以後每條邊的兩個端點權值和是奇數,問有多少種賦值方法,答案對\(998244353\)取模

\[1\leq t \leq 3 \times 10^5\\ 1\leq n \leq 3 \times 10^5,0\leq m\leq3 \times 10^5 \]

分析

顯然只有2不能和1或3組合才可以,於是可以發現把原圖抽象成2分圖,然後對兩個分部統計個數即可。

不同的連通塊可以通過乘法原理算答案。每個連通塊內一部可以填1也可以填3,也可以左邊2或者右邊2

於是每一塊的答案就是\(2^p + 2^q\)

如果連通塊不是二分圖,那麼無法做到

程式碼

vector<int> e[maxn];
ll pow2[maxn];
int col[maxn];
int c1,c2;
bool flag;

void dfs(int u,int co){
	col[u] = co;
	if(!co) c1++;
	else c2++;
	for(auto v:e[u]){
		if(col[v] < 0) dfs(v,co ^ 1);
		else if(col[v] == co){
			flag = false;
			return;
		} 
	}
}

void solve(){
	int n = readint();
	int m = readint();
	flag = true;
	for(int i = 0;i <= n;i++) e[i].clear(),col[i] = -1;
	for(int i = 0;i < m;i++){
		int x = readint();
		int y = readint();
		e[x].pb(y);
		e[y].pb(x);	
	} 
	ll ans = 1;
	for(int i = 1;i <= n;i++){
		if(col[i] == -1){
			c1 = c2 = 0;
			dfs(i,0);
			if(!flag) {
				ans = 0;
				break;
			}
			ans *= pow2[c1] + pow2[c2];
			ans %= MOD;
		}
	}
	cout << ans << '\n';
}


int main(){
	int T = readint();
	pow2[0] = 1ll;
	for(int i = 1;i < maxn;i++)
		pow2[i] = (pow2[i - 1] << 1) % MOD;
	while(T--){
		solve();
	}
}