1. 程式人生 > >CF D - Beautiful Graph(dfs 染色問題吧)給你一個圖,每個節點可以賦值1,2,3三種數字,相鄰的節點的和必須是奇數,問有多少中方法。

CF D - Beautiful Graph(dfs 染色問題吧)給你一個圖,每個節點可以賦值1,2,3三種數字,相鄰的節點的和必須是奇數,問有多少中方法。

題意

給你一個圖,每個節點可以賦值1,2,3三種數字,相鄰的節點的和必須是奇數,問有多少中方法。

分析:

很容易就可以發現如果這個圖中是有奇數的環的話,那這是肯定不行的 ,否則這個環的貢獻是為2^sumji+2^sumou , 總貢獻為每個的環的貢獻相乘,一個點也為環;

#include<bits/stdc++.h>
using namespace std ;
#define mod 998244353
#define ll long long
const int maxn= 3e5+10;
vector<int>G[maxn];
int color[maxn];
int sumji,sumou,n,m,fa; ll qsm(ll a,ll b)//快速冪 { ll ans=1; while(b) { if(b%2) ans=(ans*a)%mod; b/=2; a=(a*a)%mod; } return ans; } void init() { for(int i=1 ; i<=n ; i++) G[i].clear(); for(int i=1 ; i<=n ; i++) color[i]=0; } void dfs(int
x , int c) { if(c==1) sumji++; if(c==2) sumou++; color[x]=c; for(int i=0 ; i<G[x].size() ; i++) { if(color[G[x][i]]==0)///3-c,如果是1,那麼就變成了2,如果是2,就變成了1。如果是3,那麼就變成了0,那樣的話,就相當於沒有遍歷,以後偶還是會遍歷到的。。 dfs(G[x][i],3-c); else if(color[G[x][i]]==c)///有奇數環 { fa
=0; break; } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i=1 ; i<=m ; i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } fa=1; ll ans=1; for(int i=1 ; i<=n ; i++) { if(color[i]==0) { sumji=sumou=0; dfs(i,1); if(!fa) break; ans = (ans * (qsm(2,sumji)+qsm(2,sumou)) %mod)%mod; } } if(!fa) puts("0"); else printf("%I64d\n",ans); } }
View Code