CF1093D Beautiful Graph

给你一个 \(n\) 个点 \(m\) 条边的无向图。
你需要给每个点一个点权,使得每条边连接的两个点点权奇偶不同。点权的值域为 \(\{1,2,3\}\)
请求出方案数对 \(998244353\) 取模的结果。
图中没有重边或自环。

首先原图得是一个二分图否则无解,用并查集判断就行了
然后如果某个连通块只有一个点可以染三种颜色,否则的话一定是某一边一种颜色,另一边另一种颜色。奇数的话每个点有两种方案

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=6e5+5,P=998244353;
int fa[N],bin[N],sz[N],n,m,u,v,ans,du,dv;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void solve(){
    ans=1,n=read(),m=read();fp(i,1,n)fa[i]=i,sz[i]=1;fp(i,n+1,n*2)fa[i]=i,sz[i]=0;
    while(m--){
        u=read(),v=read(),du=find(u),dv=find(v+n);
        if(du!=dv)fa[du]=dv,sz[dv]+=sz[du];
        du=find(u+n),dv=find(v);
        if(du!=dv)fa[du]=dv,sz[dv]+=sz[du];
    }fp(i,1,n)if(find(i)==find(i+n))return (void)(puts("0"));
    fp(i,1,n)if(find(i)==i){
        if(sz[i]+sz[find(i+n)]==1)ans=3ll*ans%P;
        else ans=1ll*ans*(bin[sz[find(i)]]+bin[sz[find(i+n)]])%P;
    }
    printf("%d\n",ans);
}
int main(){
//	freopen("testdata.in","r",stdin);
    int T=read();bin[0]=1;fp(i,1,3e5+5)bin[i]=1ll*bin[i-1]*2%P;
    while(T--)solve();
    return 0;
}
posted @ 2018-12-18 22:30  bztMinamoto  阅读(168)  评论(0编辑  收藏  举报
Live2D