2011 Multi-University Training Contest 1 - Cat VS Dog

二分匹配的問題很是迷人,關鍵點就是在怎樣建圖。這道題我沒有想出來但是學習到了不少的東西。首先匈牙利算法的在main()裏面的循環是循環的是left這邊的。而find函數這是right。看來我還是沒能理解怎樣在增廣。其次就是建圖的問題,如何連邊?就是將有衝突的點連接起來。這道題我用的是喜歡貓的小孩在左邊,喜歡狗的在右邊的方式,進行構圖。其實也可以兩邊都是p個小孩。但是在最後找到最大匹配的時候需要/2。最後就是幾個二分圖不得不說的公式:1.圖G的最大團=其補圖的最大獨立集    2.最大獨立集+最小覆蓋集=V

3.最小覆蓋集=最大匹配;(最大團:圖G的頂點的子集,設D是最大團,則D中任意兩點相鄰。若u,v是最大團,則u,v有邊相連,其補圖u,v沒有邊相連,所以圖G的最大團=其補圖的最大獨立集)

上代碼:

#include<cstdio>

#include<cstring>

using namespace std;

struct node{

         intlnum;

         inthnum;

};

int g[510][510],ans,l,r;

bool y[600];

int link[600],p;

bool find(int v){

         inti;

         for(i=1;i<=r-1;i++){

         if(g[v][i]&&!y[i]){

                   y[i]=true;

                   if(link[i]==0|| find(link[i])){

                            link[i]=v;

                            returntrue;

                   }

         }

         }

         returnfalse;

 

}

 

main(){

         intn,m,i,j,num1,num2;

         nodeleft[510],right[510];

         charlike,hate;

         while(scanf("%d%d%d",&n,&m,&p)!=-1){

                   l=1;r=1;

                   for(i=1;i<=p;i++){

                            getchar();

                            scanf("%c%d%c%d",&like,&num1,&hate,&num2);

                   //      printf("\n");

                   //      printf("%c%d%c%d\n",like,num1,hate,num2);

                            if(like=='C'){

                                     left[l].lnum=num1;

                                     left[l++].hnum=num2;

                            }

                            else{

                                     right[r].lnum=num1;

                                     right[r++].hnum=num2;

                            }

                   }

                   memset(g,0,sizeof(g));

                   for(i=1;i<=l-1;i++){

                            for(j=1;j<=r-1;j++){

                                     if(left[i].lnum==right[j].hnum|| left[i].hnum==right[j].lnum)

                                     g[i][j]=1;

                            }

                   }

                   ans=0;

                   memset(link,0,sizeof(link));

                   for(i=1;i<=l-1;i++){

                   memset(y,0,sizeof(y));

                   if(find(i))ans++;

         }

                   printf("%d\n",p-ans);

         }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章