虽然说这玩意似乎没什么好写的.....
但是不经常用....时不时就忘了....还是记一些东西吧...
首先是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;
}