poj 1325(二分图最大匹配)

题意:两台机器 A, B。初始状态为0 工作模式。k项任务,其中第 i 项工作可由 A 机器的 mode_x 或者 B 机器的 mode_y 来完成。不过机器转换模式需要手动操作。
给出 k 项工作的要求,请求出完成 k 项工作最小需要的操作时。

思路:第 i 项工作可由 A 机器的 mode_x 或者 B 机器的 mode_y 来完成,最小的操作数,一定是使用最少数量的机器模式,这些模式能完成所有的工作。
以此为构图思路,将工作做边,模式做点,将问题转化为最小点覆盖集问题,而最小点覆盖集 = 最大匹配数。黑书上的例题,证明如下:

(1)  M个是足够的。只需要让它们覆盖最大匹配的这M条边,则其他边一定被覆盖

  (如果有一条边e不被覆盖,把e加入后得到一个更大的匹配)

(2)  M个是必需的。仅仅考虑形成最大匹配的这M条边,由于它们两两无公共点,

    因此至少要M个点才能把它们覆盖。

View Code
 1 // File Name: 1325.cpp

 2 // Author: Missa

 3 // Created Time: 2013/2/10 星期日 23:18:04

 4 

 5 #include<iostream>

 6 #include<cstdio>

 7 #include<cstring>

 8 #include<algorithm>

 9 #include<cmath>

10 #include<queue>

11 #include<stack>

12 #include<string>

13 #include<vector>

14 #include<cstdlib>

15 #include<map>

16 using namespace std;

17 

18 const int maxn = 1e2+5;

19 int nx,ny;//集合A的顶点数,集合B的顶点数

20 bool vis[maxn];

21 int ma[maxn][maxn];//地图

22 int link[maxn];//集合B的第Y个点与A的第X相连

23 

24 bool dfs(int x)

25 {

26     for(int y=1;y<=ny;y++)//遍历右边点集

27     {

28         if(!vis[y] && ma[x][y])

29         {

30             vis[y]=1;

31             if(link[y]==-1 || dfs(link[y]))//每次直到找到增广路

32             {

33                 link[y]=x;

34                 return true;

35             }

36         }

37     }

38     return false;

39 }

40 int maxmatch()

41 {

42     int ans=0;//最大匹配数,最小覆盖点数

43     memset(link,-1,sizeof(link));

44     for(int x=1;x<=nx;x++)

45     {

46         memset(vis,0,sizeof(vis));

47         if(dfs(x)) ans++;

48     }

49     return ans;

50 }

51 int main()

52 {

53     int k;

54     while(~scanf("%d",&nx))

55     {

56         if(!nx) break;

57         scanf("%d%d",&ny,&k);

58         int u,v,c;

59         memset(ma,0,sizeof(ma));

60         for(int i=0;i<k;i++)

61         {

62             scanf("%d%d%d",&c,&u,&v);

63             ma[u][v]=1;

64         }

65         printf("%d\n",maxmatch());

66     }

67     return 0;

68 }

 

你可能感兴趣的:(poj)