2019 ICPC上海站K.Color Graph

Color Graph

题意:给出一个由(n)个点和(m) 条边组成的无向图,保证无自环无重边,初始时所有的边都是白色的,每一次都可以选择一条边把它染成红色,不过需要保证不存在红色的奇环,现在要求尽可能多的将白边染成红色,问最多能染多少条边

题解

  • 看到奇环首先想到二分图:所以这道题就转化成了一个二分图问题:就是要找尽可能多的边使得这些边组成的图是二分图。
  • 看到数据范围首先想到状压(二进制):用一个二进制串表示每个点的状态(即是在二分图左半部分还是在右半部分呢)

第(i)位二进制位为(1),说明编号为(i)的节点在二分图左半部分。为(0)则是在右半部分。对于二进制为(1)的点,我们把它们染色为(1),对于二进制位为(0)的点,我们染色为(0),然后遍历(m)条边,如果边的两个端点颜色不同,那么符合条件的边的个数加(1),如果端点颜色一样,即两个点同在左半部或者右半部, 则不能选择这条边

AC_Code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define endl '
'
 5 const int maxn = 17*17;
 6 int a[maxn],b[maxn];
 7 bool vis[17];
 8 
 9 int main()
10 {
11     int t,cas=0;cin>>t;
12     while( t-- ){
13         int n,m; cin>>n>>m;
14         for(int i=1;i<=m;i++) cin>>a[i]>>b[i];
15         int ans=0;
16         for(int j=0;j<1<<n;j++){    //枚举状态
17             for(int k=0;k<16;k++){  //遍历状态的每一位
18                 vis[k]=(j>>k)&1;    //如果第k位为1,染色为编号为i的节点1; 否则染色为0
19             }
20             int num=0;
21             for(int i=1;i<=m;i++){
22                 num+=vis[a[i]]^vis[b[i]];//第i条边的两段的点颜色一样异或为0代表不取,不一样以后为1则取
23             }
24             ans=max(ans,num);
25         }
26         printf("Case #%d: %d
",++cas,ans);
27     }
28     return 0;
29 }
原文地址:https://www.cnblogs.com/wsy107316/p/13483497.html