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 }

 

posted @ 2013-02-10 23:39  Missa  阅读(198)  评论(0编辑  收藏  举报