标签:des style blog http color os io java strong
Time Limit: 1000 MS Memory Limit: 10000 KB
64-bit integer IO format: %I64d , %I64u Java class name: Main
5 5 10 ///n,m,k两台机器人 机器人A可完成n项工作 机器人B可完成m项工作 有K项工作
0 1 1 i,x,y 工作i可由x,y完成 以下同理
1 1 2
2 1 3
3 1 4
4 2 1
5 2 2
6 2 3
7 2 4
8 3 3
9 4 3
0
3
第一道二分图最大匹配题 类模板~~
思路:构造二分图 A的n个节点 B的m个节点 分别看成图的两个集合的顶点 如果可以在A和B上完成 则A B之间连边 则构成了二分图
本题求最小点覆盖集的问题 即最少的顶点覆盖全部的边(这样开关机器的次数就最少 因为为每一个点看成了机器) 转换成了求二分图的最大匹配问题 二分图的点覆盖数==匹配数
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; #define maxn 105 int nx,ny,jobnum; ///机器A 机器B 工作数 int g[maxn][maxn]; ///所构造的二分图 int ans; ///最大匹配数 int sx[maxn],sy[maxn]; ///path函数中DFS中用来标明顶点访问状态的数组 int cx[maxn],cy[maxn]; ///匹配情况cx[i] x集合中顶点i匹配y集合顶点cx[i]~~ int path(int u) { sx[u]=1; ///标记访问过 int v; ///变量 for(v=1; v<=ny; v++) ///一次访问y集合中的顶点 ///以B集合为遍历条件 使其与集合A相对应
{ if((g[u][v]>0)&&(!sy[v])) ///有连接&&v未访问过 { sy[v]=1; ///标记 if(path(cy[v])||(!cy[v])) ///v已经匹配了 但可以在v找到可增广路 { ///回退过程中修改可增广路的值 使匹配数加1 cx[u]=v; ///v匹配给u,u匹配给iv cy[v]=u; return 1; } } } return 0; } int solve() { ans=0; int i; memset(cx,0,sizeof(cx)); /// memset(cy,0,sizeof(cy)); for(i=1; i<=nx; i++) ///以A集合为标准 进行遍历
{ if(!cx[i]) { memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); ans+=path(i); ///可增广路扩充的 } } return 0; } int main() { int m,i,j; ///i j 对应m工作 while(scanf("%d",&nx)) ///A队nx人 B队ny人 jobnum份工作 { if(nx==0) break; scanf("%d%d",&ny,&jobnum); memset(g,0,sizeof(g)); ///初始没有边相连 for(int k=0; k<jobnum; k++) { scanf("%d%d%d",&m,&i,&j); g[i][j]=1; ///构二分图 等于1表示i j相连 } solve(); printf("%d\n",ans); } return 0; }
标签:des style blog http color os io java strong
原文地址:http://www.cnblogs.com/zhangying/p/3949920.html