1. 程式人生 > >Educational Codeforces Round 56 D - Beautiful Graph

Educational Codeforces Round 56 D - Beautiful Graph

​題目大意:

在給定的一個圖中(可能不連通) 

給每個點賦值1、2、3 使得一條邊上的兩個端點點權相加為奇數

求方案數

 

一條滿足條件的路徑上的點權必為一奇一偶交替

偶數只有2 奇數有1、3

若位於1、3、5、.... 的點有x1個 位於2、4、6、... 的點有x0個

那麼一條路徑的方案數為 2^x1+2^x0 (x1的點作為奇數點的方案+x0的點作為奇數點的方案)

當圖不連通 存在多個子圖 那麼每個子圖的方案數相乘 就是總的方案數

當圖中存在環時 若環上的點數為偶數則同樣滿足上式 但為奇數則整條路徑不可能有解

 

#include <bits/stdc++.h>
#define LL long long
#define mod 998244353
using namespace std;
int n,m;
const int N=3e5+5;
vector <int> e[N];
bool vis[N], NO;
int col[N], m0, m1;
LL p[N];
void init() {
    p[0]=1LL;
    for(int i=1;i<N;i++)
        p[i]=p[i-1]*2LL%mod;
}
void
dfs(int u,int c) { if(NO) return; col[u]=c; if(col[u]) m1++; else m0++; for(int i=0;i<e[u].size();i++) { int v=e[u][i]; if(col[v]==-1) dfs(v,c^1); else if(col[v]==col[u]) { NO=1; return; // 環上的點數為奇數個 } } } int main() { init();
int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) e[i].clear(), col[i]=-1; for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); e[u].push_back(v), e[v].push_back(u); } LL ans=1LL; NO=0; for(int i=1;i<=n;i++) if(col[i]==-1) { m0=m1=0; dfs(i,0); if(NO) break; ans=(p[m0]+p[m1])%mod*ans%mod; } if(NO) printf("0\n"); else printf("%I64d\n",ans); } return 0; }
View Code