poj 1112

二着色+DP

在不是互相認識的節點之間連一條邊,最後得到由多個連通分量構成的圖。把圖中節點分爲兩組,保證圖中每條邊的兩個頂點不能再同一組。對每個連通分量進行二着色,每個連通分量的點就分爲了a,b兩組。假定最後整個圖分爲1,2兩組。每個連通分量的a,b兩組,無非一個在1組一個在2組,通過DP,確定每個連通分量中a,b哪個在1組,哪個在2組時最有。然後就是DP的過程,沒想出來,看了其他人的結題報告。f[i][j]表示對於前i個聯通分量,是否可達到第1組和第2組的差值爲j的狀態。設a爲連通分量i的兩組的差值則f[i][j]=1當f[i-1][j-a]==1||f[i-1][j+a]==1。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 const int maxn=100+10;
  6 int g[maxn][maxn];
  7 int color[maxn];
  8 int mark[maxn][3][maxn];
  9 int amount[maxn][maxn*2];
 10 int co1[maxn][3];
 11 int n,tot;
 12 int f[maxn][maxn*2],path[maxn][maxn*2];
 13 int dfs_color(int u)
 14 {
 15     int i;
 16     for(i=1;i<=n;i++)
 17     {
 18         if(i!=u&&(!g[u][i]||!g[i][u]))
 19         {
 20             if(color[i]==color[u]) return 0;
 21             if(!color[i])
 22             {
 23                 color[i]=3-color[u];
 24                 mark[tot][color[i]][co1[tot][color[i]]++]=i;
 25                 if(!dfs_color(i)) return 0;
 26             }
 27         }
 28     }
 29     return 1;
 30 }
 31 void print(int ans)
 32 {
 33     printf("%d",amount[tot][ans]);
 34     int i,j,loc,tem=ans;
 35     for(i=tot;i>=1;i--)
 36     {
 37         loc=path[i][tem];
 38         for(j=0;j<co1[i][loc];j++) printf(" %d",mark[i][loc][j]);
 39         tem=tem-(co1[i][loc]-co1[i][3-loc]);
 40     }
 41     tem=ans;
 42     printf("\n");
 43     printf("%d",n-amount[tot][ans]);
 44     for(i=tot;i>=1;i--)
 45     {
 46         loc=3-path[i][tem];
 47         for(j=0;j<co1[i][loc];j++) printf(" %d",mark[i][loc][j]);
 48         tem=tem-(co1[i][3-loc]-co1[i][loc]);
 49     }
 50     printf("\n");
 51 }
 52 int main()
 53 {
 54     scanf("%d",&n);
 55     int i,tem,j,a;
 56     for(i=1;i<=n;i++)
 57     {
 58         while(scanf("%d",&tem)&&tem) g[i][tem]=1;
 59     }
 60     int flag=0;
 61     tot=0;
 62     for(i=1;i<=n;i++)
 63     {
 64         if(!color[i])
 65         {
 66             tot++;
 67             color[i]=1;
 68             mark[tot][1][co1[tot][1]++]=i;
 69             if(!dfs_color(i))
 70             {
 71                 flag=1;
 72                 break;
 73             }
 74         }
 75     }
 76     if(flag) printf("No solution\n");
 77     else
 78     {
 79         int a1,a2;
 80         f[1][co1[1][1]-co1[1][2]+n]=1;
 81         f[1][co1[1][2]-co1[1][1]+n]=1;
 82         path[1][co1[1][1]-co1[1][2]+n]=1;
 83         path[1][co1[1][2]-co1[1][1]+n]=2;
 84         amount[1][co1[1][1]-co1[1][2]+n]=co1[1][1];
 85         amount[1][co1[1][2]-co1[1][1]+n]=co1[1][2];
 86         for(i=2;i<=tot;i++)
 87         {
 88             a=co1[i][1]-co1[i][2];
 89             for(j=0;j<=2*n;j++)
 90             {
 91                 if((j-a)>=0&&(j-a)<=2*n&&f[i-1][j-a]==1)
 92                 {
 93                     f[i][j]=1;
 94                     path[i][j]=1;
 95                     amount[i][j]=amount[i-1][j-a]+co1[i][1];
 96                 }
 97                 else if((j+a)>=0&&(j+a)<=2*n&&f[i-1][j+a]==1)
 98                 {
 99                     f[i][j]=1;
100                     path[i][j]=2;
101                     amount[i][j]=amount[i-1][j+a]+co1[i][2];
102                 }
103             }
104         }
105 
106         for(i=n;i<=2*n;i++) if(f[tot][i]) break;
107         for(j=n-1;j>=0;j--) if(f[tot][j]) break;
108         int ans=(i-n)<(n-j)?i:j;
109         print(ans);
110     }
111     return 0;
112 }

 

發佈了187 篇原創文章 · 獲贊 3 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章