1. 程式人生 > >(二分圖最大匹配)51NOD 2006 飛行員配對

(二分圖最大匹配)51NOD 2006 飛行員配對

第二次世界大戰時期,英國皇家空軍從淪陷國徵募了大量外籍飛行員。由皇家空軍派出的每一架飛機都需要配備在航行技能和語言上能互相配合的2名飛行員,其中1名是英國飛行員,另1名是外籍飛行員。在眾多的飛行員中,每一名外籍飛行員都可以與其他若干名英國飛行員很好地配合。如何選擇配對飛行的飛行員才能使一次派出最多的飛機。對於給定的外籍飛行員與英國飛行員的配合情況,試設計一個演算法找出最佳飛行員配對方案,使皇家空 軍一次能派出最多的飛機 。對於給定的外籍飛行員與英國飛行員的配合情況,程式設計找出一個最佳飛行員配對方案, 使皇家空軍一次能派出最多的飛機。 

 

輸入

第1行有2個正整數 m 和 n。n 是皇家空軍的飛行 員總數(n<100);m 是外籍飛行員數。外籍飛行員編號為 1~m;英國飛行員編號為 m+1~n。接下來每行有 2 個正整數 i 和 j,表示外籍飛行員 i 可以和英國飛行員 j 配合。輸入最後以 2 個-1 結束。

輸出

第 1 行是最佳飛行 員配對方案一次能派出的最多的飛機數 M。如果所求的最佳飛行員配對方案不存在,則輸出‘No Solution!’。

輸入樣例

5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1

輸出樣例

4
解:具體演算法原理參考:匈牙利演算法。
鄰接矩陣做法:
 1 #include <stdio.h>
 2 
 3 int pic[101][101], vis[101], res[101], m, n;
 4 
 5 int match(int u)
 6 {
 7     for (int i = m + 1; i <= n; i++)
 8     {
 9         if (pic[u][i] && !vis[i])
10         {
11             vis[i] = 1
; 12 if (res[i] == 0 || match(res[i])) 13 { 14 res[i] = u; 15 return 1; 16 } 17 } 18 } 19 return 0; 20 } 21 22 int main() 23 { 24 while (scanf_s("%d%d", &m, &n) != EOF) 25 { 26 memset(pic, 0, sizeof pic); 27 int i = 0, j, k; 28 scanf_s("%d%d", &j, &k); 29 do 30 { 31 pic[j][k] = 1; 32 scanf_s("%d%d", &j, &k); 33 } while (j != -1); 34 for (j = 1; j <= m; ++j) 35 { 36 memset(vis, 0, sizeof vis); 37 i += match(j); 38 } 39 if (i) printf("%d", i); 40 else printf("No Solution!"); 41 } 42 return 0; 43 }

鄰接表做法:

#include <stdio.h>
typedef struct Point
{
    int pt;
    struct Point *nt;
}point;
point *spot[101];
int a[101];

int match(int j)
{    
    if (!a[j])
    { 
        for (point *temp = spot[j]; temp != NULL; temp = temp->nt)
        { 
            a[j] = 1;
            if (!a[temp->pt] || match(a[temp->pt]))
            {
                a[temp->pt] = j;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int m, n;
    while (scanf_s("%d%d", &m, &n) != EOF)
    {
        int i = 0, j, k;
        memset(spot, 0, sizeof(spot));
        memset(a, 0, sizeof(a)); 
        scanf_s("%d%d", &j, &k);
        do
        {
            point *temp = spot[j];
            if (spot[j] == NULL)
            {
                spot[j]= (point *)calloc(1, sizeof(point));
                spot[j]->pt = k;
            }
            else
            {
                while (temp->nt != NULL)
                {
                    if (temp->pt == k) goto loop;
                    temp = temp->nt;
                }
                temp->nt = (point *)calloc(1, sizeof(point));
                temp->nt->pt = k;
            }
        loop:scanf_s("%d%d", &j, &k);
        } while (j != -1);
        for (j = 1; j <= m; ++j) 
        { 
            memset(a, 0, sizeof(int)*(m + 1));
            i += match(j); 
        }
        if (i) printf("%d\n", i);
        else printf("No Solution!\n");
    }
    return 0;
}