nyoj 月老的难题【最大匹配】

来源:互联网 发布:如何在淘宝做代理商 编辑:程序博客网 时间:2024/05/16 04:45

月老的难题

时间限制:1000 ms  |  内存限制:65535 KB
难度:4
描述

月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘。

现在,由于一些原因,部分男孩与女孩可能结成幸福的一家,部分可能不会结成幸福的家庭。

现在已知哪些男孩与哪些女孩如果结婚的话,可以结成幸福的家庭,月老准备促成尽可能多的幸福家庭,请你帮他找出最多可能促成的幸福家庭数量吧。

假设男孩们分别编号为1~n,女孩们也分别编号为1~n。

输入
第一行是一个整数T,表示测试数据的组数(1<=T<=400)
每组测试数据的第一行有两个整数n,K,其中男孩的人数与女孩的人数都是n。(n<=500,K<=10 000)
随后的K行,每行有两个整数i,j表示第i个男孩与第j个女孩有可能结成幸福的家庭。(1<=i,j<=n)
输出
对每组测试数据,输出最多可能促成的幸福家庭数量
样例输入
13 41 11 32 23 2
样例输出
2

非常直观的最大匹配问题,匈牙利算法。


 #include<stdio.h>#include<string.h>const int maxn=1005;int link[maxn],vis[maxn],head[maxn],cnt;struct Edge{int to,next;}edge[maxn*maxn];void init(){cnt=0;memset(head,-1,sizeof(head));memset(link,-1,sizeof(link));}void add(int u,int v){edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}int dfs(int u){for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(!vis[v]){vis[v]=1;if(link[v]==-1||dfs(link[v])){link[v]=u;return 1;}}}return 0;}int match(int n){int ans=0;for(int i=1;i<=n;++i){memset(vis,0,sizeof(vis));if(dfs(i)){++ans;}}return ans;}int main(){int t,m,n;//freopen("shuju.txt","r",stdin);scanf("%d",&t);while(t--){init();scanf("%d%d",&n,&m);for(int i=0;i<m;++i){int u,v;scanf("%d%d",&u,&v);add(u,v);//不需要双向边}int ans=match(n);printf("%d\n",ans);}return 0;}        




0 0