二分圖最大分配

二分圖是一個無向圖,分爲x,y兩部分,x部中的點與y中的點每每會存在多條無向邊,若x1與y2之間存在一條邊,那麼x1與y2能夠「分配」,固然每一個點部止侷限於只有一條邊,能夠有多條,因此又有多種分配方法,爲達到讓這個二分圖中分配數量最大,即便x1與y2能夠「分配」也只是暫時的,由於要爲其餘點「讓步」,舉個例子:ios

圖中,點1到點2有一條邊,點1到點3有一條邊,點2到點4有一條邊git

就「擇近原則」,點1能夠首先和點2「分配」,但點3發現本身只有點1能夠「分配」,因而就向點1提出要求「分配」,但是點1已經被「分配過了」,因而點1就去找點2商量問它可不能夠找另外一個點「分配」,點2就去詢問點4可否「分配」,發現點4尚未被「分配」,也就是說點2能夠找另外一個點分配,因而返回true,不和點1「分配」了,和點4分配,點1獲得true便與點3「分配」了算法

細心的人可能會發現,若是像開始那樣:點1與點2分配,那麼只有1個「分配組」,而通過這一系列算法(匈牙利算法)而拓展路線(增廣路)便有2個「分配組」,這就稱爲二分圖最大分配ide

題目連接函數

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;  5 int m;  6 int n;  7 int x,y;  8 int ans;  9 int match[210];                                  //記錄分配目標 
10 int put[110][3];                                 //輸出 
11 bool book[210];                                  //記錄剪枝 
12 bool way[210][210];                              //記錄無向圖的邊 
13 inline int read()                                //快速讀入 
14 { 15     int sign=1,num=0; 16     char ch=getchar(); 17     while(!isdigit(ch)){if(ch=='-')sign=-1;ch=getchar();} 18     while(isdigit(ch)){num=num*10+(ch-'0');ch=getchar();} 19     return sign*num; 20 } 21 void init()                                      //讀入函數 
22 { 23     m=read(); 24     n=read(); 25     while(x!=-1&&y!=-1) 26  { 27         x=read();                                //無向邊存兩次 
28         y=read(); 29         way[x][y]=true; 30         way[y][x]=true; 31  } 32 } 33 bool dfs(int x) 34 { 35     for(int y=m+n;y>0;--y) 36  { 37         if(way[x][y]&&book[y]==false)            //枚舉點x的邊 
38  { 39             book[y]=true;                        //記錄點y已被查找(並不是分配) 
40             if(match[y]==0||dfs(match[y]))       //若y沒有被分配或與y分配的人還有"退"的餘地 
41  { 42                 match[x]=y;                      //儲存分配目標 
43                 match[y]=x; 44                 return true; 45  } 46  } 47  } 48     return false; 49 } 50 int main()                                       //看代碼建議從mian函數看起 
51 { 52  init(); 53     for(int i=1;i<=m+n;++i)                      //枚舉點 
54  { 55         memset(book,false,sizeof(book)); 56  dfs(i); 57  } 58     for(int i=1;i<=m+n;++i) 59         if(match[i]!=0&&match[match[i]]!=0)       //防止重複輸出 
60  { 61             put[++ans][1]=i; 62             put[ans][2]=match[i]; 63             match[match[i]]=0; 64  } 65     if(ans==0)                                   //特判 
66  { 67         puts("No Solution!"); 68         return 0; 69  } 70     printf("%d",ans); 71     for(int i=1;i<=ans;++i) 72         printf("\n%d %d",put[i][1],put[i][2]); 73 }
View Code
相關文章
相關標籤/搜索