http://acm.nyist.net/JudgeOnline/problem.php?pid=239
此题为二分最大匹配入门之必备习题之一!
话不多,上代码~
代码1:邻接表+匈牙利算法(邻接矩阵貌似会tle,此题数据量较大)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct EdgeNode
{
int adjvex;
struct EdgeNode *next;
};
struct VexNode
{
struct EdgeNode *firstedge;
};
struct VexNode alist[510];
int visit[501],match[510];
int find(int x)
{
<span style="white-space:pre"> </span>int k;
<span style="white-space:pre"> </span>struct EdgeNode *p;
<span style="white-space:pre"> </span>p=alist[x].firstedge;
<span style="white-space:pre"> </span>while (p)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>k=p->adjvex;
<span style="white-space:pre"> </span>if (!visit[k])
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>visit[k]=1;
<span style="white-space:pre"> </span>if (!match[k]||find(match[k]))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>match[k]=x;
<span style="white-space:pre"> </span>return 1;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>p=p->next;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return 0;
}
int main()
{
<span style="white-space:pre"> </span>int n,t,k,i,ans,vi,vj;
<span style="white-space:pre"> </span>struct EdgeNode *s;
<span style="white-space:pre"> </span>scanf("%d",&t);
<span style="white-space:pre"> </span>while (t--)
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>scanf("%d%d",&n,&k);
<span style="white-space:pre"> </span>memset(alist,0,sizeof(alist));
<span style="white-space:pre"> </span>memset(match,0,sizeof(match));
<span style="white-space:pre"> </span>for (i=1;i<=k;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>scanf("%d%d",&vi,&vj);
<span style="white-space:pre"> </span>s=(struct EdgeNode*)malloc(sizeof(struct EdgeNode));
<span style="white-space:pre"> </span>s->adjvex=vj;
<span style="white-space:pre"> </span>s->next=alist[vi].firstedge;
<span style="white-space:pre"> </span>alist[vi].firstedge=s;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>for (i=1,ans=0;i<=n;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>memset(visit,0,sizeof(visit));
<span style="white-space:pre"> </span>if (find(i)) ans++;
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>printf("%d\n",ans);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return 0;
}
</pre><pre name="code" class="cpp"><img src="https://img-blog.youkuaiyun.com/20140807152147938?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQVExNEFRMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
</pre><pre name="code" class="cpp">
代码2:最大流
思路:在原二分图的基础上,做几点修改,增加一个超级源点,并把源点和集合U(设二分图的点为两个集合U和V)中的每个点连成有向边,容量为1,再增加一个超级汇点,并把集合V中的每个点于汇点连成有向边,容量为1。
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#define MAXM 30010
#define MAXN 1010
#define oo 0x7fffffff
struct Dinic
{
struct node
{
int x,y,c,next;
}line[MAXM];
int Lnum,_next[MAXN],dis[MAXN];
void initial(int n)
{
for (int i=0;i<=n;i++) _next[i]=-1;
Lnum=-1;
}
void addline(int x,int y,int c)
{
line[++Lnum].next=_next[x],_next[x]=Lnum;
line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c;
line[++Lnum].next=_next[y],_next[y]=Lnum;
line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0;
}
int BFS(int s,int e)
{
queue<int> Q;
while (!Q.empty()) Q.pop();
memset(dis,-1,sizeof(dis));
dis[s]=0;
Q.push(s);
while (!Q.empty())
{
int h,k;
h=Q.front(),Q.pop();
if (h==e) return dis[e];
for (k=_next[h];k!=-1;k=line[k].next)
if (line[k].c && dis[line[k].y]==-1)
dis[line[k].y]=dis[h]+1,Q.push(line[k].y);
}
return false;
}
int dfs(int x,int flow,int e)
{
if (x==e) return flow;
int temp,cost=0;
for (int k=_next[x];k!=-1;k=line[k].next)
if (line[k].c && dis[line[k].y]==dis[x]+1)
{
temp=dfs(line[k].y,min(flow-cost,line[k].c),e);
if (temp)
{
line[k].c-=temp,line[k^1].c+=temp;
cost+=temp;
if (flow==cost) return cost;
}else dis[line[k].y]=0;
}
return cost;
}
int MaxFlow(int s,int e)
{
int MaxFlow=0;
while (BFS(s,e))
MaxFlow+=dfs(s,oo,e);
return MaxFlow;
}
}T;
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
int n,k;
scanf("%d%d",&n,&k);
int N=2*n+1;
T.initial(N);
int v1[501],v2[501];
memset(v1,0,sizeof(v1));
memset(v2,0,sizeof(v2));
for (int i=0;i<k;++i)
{
int u,v;
scanf("%d%d",&u,&v);
T.addline(u,v+n,1);
if (v1[u]==0)
{
v1[u]=1;
T.addline(0,u,1);
}
if (v2[v]==0)
{
v2[v]=1;
T.addline(v+n,N,1);
}
}
int ans=T.MaxFlow(0,N);
printf("%d\n",ans);
}
return 0;
} #include<iostream>
using namespace std;
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#define MAXM 30010
#define MAXN 1010
#define oo 0x7fffffff
struct Dinic
{
struct node
{
int x,y,c,next;
}line[MAXM];
int Lnum,_next[MAXN],dis[MAXN];
void initial(int n)
{
for (int i=0;i<=n;i++) _next[i]=-1;
Lnum=-1;
}
void addline(int x,int y,int c)
{
line[++Lnum].next=_next[x],_next[x]=Lnum;
line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c;
line[++Lnum].next=_next[y],_next[y]=Lnum;
line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0;
}
int BFS(int s,int e)
{
queue<int> Q;
while (!Q.empty()) Q.pop();
memset(dis,-1,sizeof(dis));
dis[s]=0;
Q.push(s);
while (!Q.empty())
{
int h,k;
h=Q.front(),Q.pop();
if (h==e) return dis[e];
for (k=_next[h];k!=-1;k=line[k].next)
if (line[k].c && dis[line[k].y]==-1)
dis[line[k].y]=dis[h]+1,Q.push(line[k].y);
}
return false;
}
int dfs(int x,int flow,int e)
{
if (x==e) return flow;
int temp,cost=0;
for (int k=_next[x];k!=-1;k=line[k].next)
if (line[k].c && dis[line[k].y]==dis[x]+1)
{
temp=dfs(line[k].y,min(flow-cost,line[k].c),e);
if (temp)
{
line[k].c-=temp,line[k^1].c+=temp;
cost+=temp;
if (flow==cost) return cost;
}else dis[line[k].y]=0;
}
return cost;
}
int MaxFlow(int s,int e)
{
int MaxFlow=0;
while (BFS(s,e))
MaxFlow+=dfs(s,oo,e);
return MaxFlow;
}
}T;
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
int n,k;
scanf("%d%d",&n,&k);
int N=2*n+1;
T.initial(N);
int v1[501],v2[501];
memset(v1,0,sizeof(v1));
memset(v2,0,sizeof(v2));
for (int i=0;i<k;++i)
{
int u,v;
scanf("%d%d",&u,&v);
T.addline(u,v+n,1);
if (v1[u]==0)
{
v1[u]=1;
T.addline(0,u,1);
}
if (v2[v]==0)
{
v2[v]=1;
T.addline(v+n,N,1);
}
}
int ans=T.MaxFlow(0,N);
printf("%d\n",ans);
}
return 0;
}