假如有n个帅哥,每个帅哥有m个的理想女友,他们只想与这m个美女中的其中一个谈恋爱,请问最多能出现几对情侣????????????????????????????????????????????????????????????????????????????????????????
比如:
A喜欢 a b
B喜欢 a c
C喜欢 c
那么就让A和b在一起 B和a C和c中随便一个美女在一起,就可以出现三对
如果让A和a在一起 B和c在一起 C就只能是单身狗了, 就只有两对
这种问题叫二分图的最大匹配,用匈牙利算法求解。
最小顶点覆盖数 = 最大匹配
最大独立集数 = 最小路径覆盖数 = 节点数 - 最大匹配
例题 hoj1150. hoj1151.
#include <bits/stdc++.h> /*最小顶点覆盖数 = 最大匹配 最大独立集数 = 最小路径覆盖数 = 节点数 - 最大匹配 */
#define ll long long
#define T int t;scanf("%d", &t);while(t--)
using namespace std;
const int mod = 1e9 + 7;
int k,n,m;
int vis[505]; //存右边集合的点有没有被匹配
int ans = 0;
int father[505]; //表示本次找增广路时有无经过,防止重复死循环
int mp[505][505];
struct node{
int to;
int nxt;
}edge[10000];
int cnt = 0;
int head[1000];
void add(int u,int v){
edge[cnt].to = v;
edge[cnt].nxt = head[u];
head[u] = cnt ++;
}
int dfs(int u, int root){
if(father[u] == root) return 0;
father[u] = root;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(vis[v] == 0 || dfs(vis[v],root)){
vis[v] = u;
return 1;
}
}
return 0;
}
int main(){
scanf("%d %d %d", &n, &m, &k); //n个帅哥,m个美女
memset(head,-1,sizeof(head));
for(int i = 0; i < k; i ++){
int u,v;
scanf("%d %d", &u, &v);
add(u,v); //建边,表示u可以和v在一起
}
for(int i = 1; i <= n; i ++){
if(head[i] != -1){
if(dfs(i,i)) ans ++;
}
}
printf("%d\n", ans);
return 0;
}