(二分图最大匹配)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;
} 

猜你喜欢

转载自www.cnblogs.com/Ekalos-blog/p/10221883.html
今日推荐