题意:给你两台机器A和B,A机器有n种模式,B机器有m种模式,初始时都是0,现在给你k个任务,每个任务可以由机器A的x模式完成或者机器B的y模式完成,而每次改变机器的模式都要重启一次,问你最少的重启次数使得完成所有任务。
建图:机器A和机器B的模式互相连接,某个任务由A的x和B的y完成那么x与y相连
在这个二分图中找出最少的点使得所有的边都至少有一个端点被选中
最小点覆盖 = 最大匹配
3个重要结论:
最大匹配数:最大匹配的匹配边的数目
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立集:选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
最小点覆盖数=最大匹配数
最小路径覆盖 =顶点数-最大匹配数
二分图最大独立集 = 顶点数 - 最大匹配数
链接:hdu 1150
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 2555;
int used[maxn];
int link[maxn];
int mat[maxn][maxn];
int gn, gm;
int dfs(int t) {
for(int i = 1; i <= gm; i++) {
if(!used[i] && mat[t][i]) {
used[i] = 1;
if(link[i] == -1 || dfs(link[i])) {
link[i] = t;
return 1;
}
}
}
return 0;
}
int maxmatch() {
int num = 0;
memset(link, 0xff, sizeof(link));
for(int i = 1; i <= gn; i++) {
memset(used, 0, sizeof(used));
if(dfs(i)) {
num++;
}
}
return num;
}
int main()
{
int n, m, k;
while(~scanf("%d", &n) && n){
scanf("%d %d", &m, &k);
memset(mat, 0, sizeof(mat));
gn = n;
gm = m;
int a, x, y;
for(int i = 0; i < k; i++) {
scanf("%d %d %d", &a, &x, &y);
mat[x][y] = 1;
}
int res = maxmatch();
printf("%d\n", res);
}
return 0;
}