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); } }