zoukankan      html  css  js  c++  java
  • Codeforces 1093D Beautiful Graph|二分图染色

    题目链接

    蒟蒻第一次通过CF D题~QAQ

    言归正传。本题的大意是给每个点赋上$1$、$2$ 、$3$这三种点权之一,使得每条边所连的两个点的点权之和为奇数,问有多少种赋值方案。

    首先,我们知道“奇数+偶数=奇数”。显然,凡是能赋值为1的点一定能赋值为3。所以其实我们对于每个点,只有赋值为奇数或偶数两种选择。一旦一条边所连的一个点被赋值为奇数,那么另外一个点就要被赋值为偶数。(有没有发现很像二分图?)

    那么,对于每个连通块,我们可以类似用二分图判定的染色法:选定一个起点先行染色,然后用搜索对每个点进行染色。如果染色出现了冲突,整张图的方案数就为$0$。

    设此连通块中有$n$个点,$c1$个点被赋值成了奇数,根据乘法原理,这个连通块中赋值方案为$2^{c1}+2^{n-c1}$。($2^{n-c1}$是因为将每个点取反依然可行)同样根据乘法原理,整张图的染色方案是每个联通块的方案数相乘之积。

    对于求$2^x$,我们可以用快速幂去求。

    上代码

    #include<bits/stdc++.h>
    using namespace std;
    const long long mod=998244353;
    int cc,to[900000],net[900000],fr[900000],q[900000],color[900000],ttt,n,m,u,v,h,t;
    long long ans,cnt1;
    bool vis[900000];
    void addedge(int u,int v)
    {
        cc++;
        to[cc]=v;net[cc]=fr[u];fr[u]=cc;
    }
    long long p(int x)
    {
    //快速幂求2^x
        long long ans=1,kkk=2;
        while (x)
        {
            if (x&1) 
            {
                ans*=kkk;
                ans%=mod;
            }
            kkk*=kkk;
            kkk%=mod;
            x>>=1;
        }
        return ans;
    }
    int main()
    {
        scanf("%d",&ttt);
        for (int tt=1;tt<=ttt;tt++)
        { 
          scanf("%d%d",&n,&m);
          for (int i=1;i<=m;i++)
          {
          	 scanf("%d%d",&u,&v);
          	 addedge(u,v);
          	 addedge(v,u);
          }
          int bb=1;ans=1;
          while (1)
          {
          	 h=1;t=1;q[1]=bb;vis[bb]=1;color[bb]=1;cnt1=1;
          	 while (h<=t)
          	 {
    //BFS染色
    
          	 	 for (int i=fr[q[h]];i;i=net[i])
          	 	 {
          	 	 	int y=to[i];
          	 	 	if (!vis[y])
          	 	 	{
          	 	 		color[y]=3-color[q[h]];
          	 	 		if (color[y]==1) cnt1++; 
          	 	 		q[++t]=to[i];
          	 	 		vis[y]=1;
          	 	 	}
          	 	 	else
          	 	 	{
          	 	 		if (color[y]!=3-color[q[h]]) ans=0;
          	 	 	}
          	 	 }
          	 	 h++;
          	 }
          	 ans*=(p(cnt1)%mod+max(p(t-cnt1),(long long)(1))%mod)%mod;
          	 ans%=mod;
          	 for (int i=bb+1;i<=n;i++)
          	 {
          	 	 if (!vis[i]) {bb=i;break;}//找未被遍历的连通块
          	 }
          	 if (bb==q[1]) break;
          }
          for (int i=1;i<=n;i++)
            fr[i]=0,vis[i]=false,color[i]=0;
          cc=0;
          printf("%d
    ",ans%mod);
        }
        return 0;
    }
    

      

      Tags:,二分图,图论,快速幂

      

  • 相关阅读:
    Thinkpad R400无线网络一个都不见了!
    如果使用安卓4.4的SD卡?
    如何使用安卓4.4的SD卡?
    在IAR使用FreeRTOS出现Error[Pa045]: function "XXX" has no prototype
    DSP5509的RTC实验-第3篇
    LWM2M简介-学习记录
    DSP5509的定时器实验-第2篇
    DSP5509的XF实验-第一篇
    华为LiteOS系统使用-任务调度函数-第一篇
    2017-12-24自选的股票之春秋航空
  • 原文地址:https://www.cnblogs.com/fmj123/p/CF1093D.html
Copyright © 2011-2022 走看看