1. 程式人生 > 實用技巧 >2019 ICPC上海站K.Color Graph

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 '\n'
 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\n",++cas,ans); 27 } 28 return 0; 29 }