谈恋爱问题

假如有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;
}

你可能感兴趣的:(图)