二着色+DPios
在不是互相認識的節點之間連一條邊,最後獲得由多個連通份量構成的圖。把圖中節點分爲兩組,保證圖中每條邊的兩個頂點不能再同一組。對每一個連通份量進行二着色,每一個連通份量的點就分爲了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。spa
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 }