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 }