2019 ICPC上海站K.Color Graph
阿新 • • 發佈:2020-08-11
題意:給出一個由\(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 }