二分图匹配模板

虽然说这玩意似乎没什么好写的.....

但是不经常用....时不时就忘了....还是记一些东西吧...


首先是Hungary算法.....邻接矩阵实现.....

bool M[205][205];
bool used[205];
int mat[205];

bool DFS(int x)
{
	for(int i=0;i<m;i++)
	if(M[x][i] && !used[i])
	{
		used[i]=true;
		if( mat[i]==-1 || DFS(mat[i]) )
		{
			mat[i]=x;
			return true;
		}
	}
	return false;
}
.....
	int res=0;
	memset(mat,0xFF,sizeof(mat));
	for(int i=0;i<n;i++)
	{
		memset(used,0,sizeof(used));
		res+=DFS(i);
	}
.....

M是边表,存储集合A到集合B的有向边.

使用used来使得对于每次搜索,集合B只访问一次.

mat[i]表示集合B中元素i,在A中对应的元素是哪个.

要点:

1.注意对应关系.我们只存储从集合A到集合B的边.used的tag打在集合B的元素上.

2.千万别忘了初始化....

3.由于算法复杂度比较高,所以一般不会吝啬地用链表邻接表.如果可匹配得边数比较少而点数比较多,就用链表邻接表.

下面是邻接表写的Hungary.没什么区别...

struct edge
{
	int in;
	edge*nxt;
}pool[50000];
edge*et=pool;
edge*eds[205];
void addedge(int i,int j)
{ et->in=j; et->nxt=eds[i]; eds[i]=et++; }
#define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)


bool used[205];
int mat[205];

bool DFS(int x)
{
	FOREACH_EDGE(i,x)
	if(!used[i->in])
	{
		used[i->in]=true;
		if( mat[i->in]==-1 || DFS(mat[i->in]) )
		{
			mat[i->in]=x;
			return true;
		}
	}
	return false;
}
.....
.....
int res=0;
memset(mat,0xFF,sizeof(mat));
for(int i=0;i<n;i++)
{
	memset(used,0,sizeof(used));
	res+=DFS(i);
}
....
....


如果是带权匹配的话.....

果断网络流!

不就是120行嘛!

顺便贴了新的文件头.....


#include <cstdio>
#include <fstream>
#include <iostream>

#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>

#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <list>

typedef unsigned int uint;
typedef long long int ll;
typedef unsigned long long int ull;
typedef double db;

#define DBG printf("*")

using namespace std;

int getint()
{
	int res=0;
	char c=getchar();
	bool mi=false;
	while( (c<'0' || c>'9') && !feof(stdin) ) mi=(c=='-'),c=getchar();
	while( ('0'<=c && c<='9') && !feof(stdin) ) res=res*10+c-'0',c=getchar();
	return mi ? -res : res;
}
ll getll()
{
	ll res=0;
	char c=getchar();
	bool mi=false;
	while( (c<'0' || c>'9') && !feof(stdin) ) mi=(c=='-'),c=getchar();
	while( ('0'<=c && c<='9') && !feof(stdin) ) res=res*10+c-'0',c=getchar();
	return mi ? -res : res;
}
void fillarray(int*k,int v,int size)
{ for(int i=0;i<size;i++) k[i]=v; }
void fillarray(ll*k,ll v,int size)
{ for(int i=0;i<size;i++) k[i]=v; }
void fillarray(char*k,char v,int size)
{ for(int i=0;i<size;i++) k[i]=v; }
void fillarray(db*k,db v,int size)
{ for(int i=0;i<size;i++) k[i]=v; }

//==============================================================================
//==============================================================================
//==============================================================================
//==============================================================================


db INF=1e20;
db eps=1e-11;
bool fequal(db a,db b)
{ return fabs(a-b)<eps; }

//maxflow

struct edge
{
	int in;
	int c;
	db v;
	edge*nxt;
	edge*ptr;
}pool[100000];
edge*et=pool;
edge*eds[1000];
void addedge(int i,int j,int c,db v)
{
	et->ptr=et+1;
	et->in=j; et->c=c; et->v=v; et->nxt=eds[i]; eds[i]=et++;
	et->ptr=et-1;
	et->in=i; et->c=0; et->v=-v; et->nxt=eds[j]; eds[j]=et++;
}
#define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)

int n;
int st,ed;

db cost;
db dist[1000];
bool used[1000];
int DFS(int x,int mi)
{
	if(x==ed) return mi;
	used[x]=true;
	int res=0; int c;
	FOREACH_EDGE(i,x)
	if(i->c>0 && !used[i->in] && fequal(dist[x]+i->v,dist[i->in]) && ( c=DFS(i->in,min(i->c,mi)) ))
	{
		res+=c;
		i->c-=c;
		i->ptr->c+=c;
		mi-=c;
		cost+=db(c)*i->v;
		if(mi==0) break; 
	}
	used[x]=false;
	if(res==0) dist[x]=INF;
	return res;
}

int qh,qt;
int q[4000000];
db DINIC()
{
	db res=0.0;
	
	while(true)
	{
		fillarray(dist,INF,n);
		qh=qt=0;
		q[qt++]=st;
		dist[st]=0;
		while(qh!=qt)
		{
			int&cur=q[qh];
			FOREACH_EDGE(i,cur)
			if( i->c>0 && dist[i->in] > dist[cur] + i->v )
			{
				dist[i->in]=dist[cur]+i->v;
				q[qt++]=i->in;
			}
			qh++;
		}
		
		if(dist[ed]>=INF) break;
		
		cost=0;
		if(0==DFS(st,(1<<28)-1)) break;
		res+=cost;
	}
	
	return res;
}


//=================================================

int ptot;
int mx[1050];
int my[1050];
int ex[1050];
int ey[1050];

db dst(int i,int j)
{ return sqrt(db(mx[i]-ex[j])*db(mx[i]-ex[j])+db(my[i]-ey[j])*db(my[i]-ey[j])); }

//blocks define
#define MISSILE(i) (i)
#define ENEMY(i) ((i)+ptot)

int main()
{
	ptot=getint();
	for(int i=0;i<ptot;i++)
	mx[i]=getint(),my[i]=getint();
	for(int i=0;i<ptot;i++)
	ex[i]=getint(),ey[i]=getint();
	
	st=ptot*2;
	ed=st+1;
	n=ed+1;
	
	for(int i=0;i<ptot;i++)
	for(int j=0;j<ptot;j++)
	addedge(MISSILE(i),ENEMY(j),1,dst(i,j));
	
	for(int i=0;i<ptot;i++)
	addedge(st,MISSILE(i),1,0.0);
	
	for(int i=0;i<ptot;i++)
	addedge(ENEMY(i),ed,1,0.0);
	
	printf("%.3lf\n",DINIC());
	
	return 0;
}


posted @ 2015-01-26 16:50 DragoonKiller 阅读(...) 评论(...) 编辑 收藏