Codeforces 1093D. Beautiful Graph【二分图染色】+【组合数】

<题目链接>

题目大意:

给你一个无向图(该无向图无自环,且无重边),现在要你给这个无向图的点加权,所加权值可以是1,2,3。给这些点加权之后,要使得任意边的两个端点权值之和为奇数,问总共有多少种可能?结果mod 998244353。

解题分析:

整张图的所有顶点赋权之后,一定分为奇、偶两部分点集,并且,要想使的该图满足条件,任意边的两个端点的奇偶性应该是不同的,所以我们可以用DFS对图进行二分图染色,将图分为两个部分,需要注意的是,该图未必连通。然后就是DFS的过程中,如果下一个点已经染过色,且颜色与当前点颜色相同,说明该图不符合条件。将当前连通分量分成两部分之后,也有两种情况,一是:第一部分为奇数,因为奇数有1、3两种选择,所以情况有 2^cnt1 种 ;二是:第二部分是奇数,则情况有 2^cnt2 种。然后再将所有连通分量的情况相乘,就是最终得到的所有情况。

 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 #define rep(i,s,t) for(int i=s;i<=t;i++)
 7 typedef long long ll;
 8 const ll mod = 998244353;
 9 const int N =  3*1e5+10;
10 int n,m,cnt1,cnt2;
11 vector<int>G[N];
12 int color[N];
13 ll ans,fact[N];
14 bool fp;
15
16 void dfs(int u){
17     if(color[u]==1)cnt1++;     //1部分的个数
18     else cnt2++;     //2部分的个数
19     for(int i=0;i<G[u].size();i++){
20         int v=G[u][i];
21         if(color[u]==color[v]){ fp=false; return ;}   //如果染色时,发现相邻两点颜色相同,则出现冲突,说明该图不符合条件
22         if(color[v])continue;
23         if(color[u]==1)color[v]=2;       //将相邻两点分成不同部分
24         else if(color[u] == 2)color[v]=1;
25         dfs(v);
26     }
27 }
28
29 int main(){
30     fact[0]=1;for(int i=1;i<N;i++)fact[i]=fact[i-1]*2%mod;
31     int T;scanf("%d",&T);while(T--){
32         scanf("%d%d",&n,&m);
33         rep(i,0,n)G[i].clear(),color[i]=0;
34         rep(i,1,m){
35             int u,v;scanf("%d%d",&u,&v);
36             G[u].push_back(v);G[v].push_back(u);
37         }
38         fp=true;ans=1;
39         rep(i,1,n) if(!color[i]){
40             cnt1=cnt2=0;
41             color[i]=1;dfs(i);    //将当前连通分量利用二分图染色法分成1、2两个不同的部分
42             if(!fp){ans=0;break;}
43             ans*=(ll)(fact[cnt1]+fact[cnt2]);  //如果1的部分填奇数,因为每个奇数点都有两种选择,所以有fact[cnt1]种情况,如果2的部分填奇数,则有fact[cnt2]种情况
44             ans %= mod;
45         }
46         printf("%lld\n",ans%mod);
47     }
48 }

2018-12-30

原文地址:https://www.cnblogs.com/00isok/p/10199276.html

时间: 2024-08-29 11:30:05

Codeforces 1093D. Beautiful Graph【二分图染色】+【组合数】的相关文章

hdu5313Bipartite Graph(二分图染色+DP(bitset优化))

题意:给n个点m条边,问最多可以添加几条边使图为完全二分图 分析:如果二分图没有限制,看到是两边分别为n/2个点和n-n/2个点的最优但是可   能出现大于此点的情况,比如n=4,m=3,边为1 2,1 3,1 4.此时完全二分图边最多为3,所以要求得二分图左边或者右边可达到的离n/2最近的点数是多少为最优解,于是采用染色分别求出各个联通快的2种颜色的各个点数,然后用推出能达到的点数,这里dp[i]的下一个状态是dp[i+1]+d[i+1][0]和dp[i+1][1](dp[i]为前i个二分图的

CodeForces - 862B Mahmoud and Ehab and the bipartiteness(二分图染色)

题意:给定一个n个点的树,该树同时也是一个二分图,问最多能添加多少条边,使添加后的图也是一个二分图. 分析: 1.通过二分图染色,将树中所有节点分成两个集合,大小分别为cnt1和cnt2. 2.两个集合间总共可以连cnt1*cnt2条边,给定的是一个树,因此已经连了n-1条边,所以最多能连cnt1*cnt2-(n-1)条边. 3.注意输出. #include<cstdio> #include<cstring> #include<cstdlib> #include<

noip 2010 关押罪犯 (二分图染色 并茶几)

/* 二分图染色版本 两个监狱对应二部图的两部分 在给定的怨气值里二分 对于每一个Ci 进行染色判断是否合法 染色的时候 如果这条边的ci > Ci 这两个人就带分开 即染成不同的颜色 如果染色到某两个点颜色相同且怨气值>Ci 这个Ci就不合法 二分直到最后答案 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100

[2016-03-08][651][codeforces][B][Beautiful Paintings]

[2016-03-08][651][[codeforces]][B][Beautiful Paintings] 题目编号:CF 651 B 题目大意:画展有n个画,每个画beauty值已知,客人每经过一个比之前一个画更美的,客人会变得beauty,重新安排画的顺序,求客人开心时间的最大值 输入:n 和每个话的beauty 输出:时间 分析: 如果beauty为a的画,数量为 k,那么beaty小于或者大于a的k个,总能安排让客人开心,所以,除了数量k最大的那个beauty之外,每个beauty总

Codeforces 55D Beautiful Number

Codeforces 55D Beautiful Number a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. Input The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two

【hiho】hiho第三十周&#183;二分图染色判定

是时候认真学学二分图了... 光会模板没用的,打好基础最重要~ 题目: 字面意思,二分图染色判断,判断是否是二分图 思路: 要让该无向图成为一张二分图,必须得将点划为G1,G2两个集合 也就是,对于给定的任何一条边,其连接的两个节点不能同色 那么我们可以总结出一个方法: 对于当前结点: 1.若其未被染色,我们规定将其染成A色,记为1 2.遍历其所有相邻的染色点,有未染色的,染为B色,记为2,DFS之 注:一旦被染色,说明此点状态被唯一确定 那么我们可以得到判断条件: 1.染色过程是否发生冲突 附

CodeForces 21D Traveling Graph 状压dp+欧拉回路

题目链接:点击打开链接 题意: 给定n个点m条边的无向图 求从1点开始经过每条边至少一次最后回到1点的最小路程 显然就是找一条路径可重复的欧拉回路 思路: 首先对于欧拉回路的结论是:所有点的度数都为偶数 因为所有边至少经过一次,那么可以把题意转换成加最少多少条边使得图满足以上结论 而加的边目的是为了把奇度数转成偶度数,先floyd一下得到任意点间加边的最小花费 dp[i]表示状态i下度数都为偶数的最小花费. 状压dp,把i状态下,所有未选择的点中挑2个奇度数的转移即可. #include <cs

UVA11080- Place the Guards(二分图染色)

题目链接 题意:放最少的士兵去监视所有的道路, 但士兵不可相邻,符合的话,就输出最少的士兵数,否则输出-1 思路:其实就是二分图染色,即黑白染色,然后选择黑白染色最少的那个颜色累加,但要注意可能有多个连通块,只要有一个连通块不符合的话,就不符合. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> u

POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络进行一次遍历就可以了,比较简单. 建图:同样是一个二分图,左边的点代表去掉出边, 右边的点代表去掉入边(小心别弄混),左边去掉出边的点与源点相连, 容量为wi- . 然后更据给出的弧进行连线,权值为INF 使用很好理解的EK算法:(360MS) //#pragma comment(linker, "