[省选前题目整理][LA 4043]Ants(二分图最小权匹配)
2015-03-27 08:43
465 查看
题目链接
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=14347题目大意
有nn个白点、nn个黑点,要在平面中连nn条边,保证每条边连接的是一个白点和一个黑点,且任意两条边不相交,求出一个合法方案。思路
我们可以将所有的白点看成xx侧,把所有的黑点看成yy侧,每个白点和所有的黑点连边,权值为这两点之间的欧几里得距离,然后跑KM算法,或者再创建超级源点和超级汇点,跑费用流,最终均可得到这个二分图的最小权匹配,这就是答案。为什么这个思路是正确的呢?我们可以画个图看看:
考虑如上图左的情况,两个白点和两个黑点连边,两个边有交叉,如果我们把这两个边换成不交叉的边(如上图右),则这两个边的权值之和必然减少,正确性显然。
代码
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <cmath> #define MAXV 300 #define MAXE 60000 #define INF 1e9 using namespace std; int S,T; struct Edge { int u,v,cap,next; double w; }edges[MAXE]; int head[MAXV],nCount=0; void AddEdge(int U,int V,int C,double W) { edges[++nCount].u=U; edges[nCount].v=V; edges[nCount].cap=C; edges[nCount].w=W; edges[nCount].next=head[U]; head[U]=nCount; } void add(int U,int V,int C,double W) { AddEdge(U,V,C,W); AddEdge(V,U,0,-W); } int pre[MAXV],q[MAXE]; double dist[MAXV]; bool inQueue[MAXV]; bool SPFA() { memset(inQueue,false,sizeof(inQueue)); //!!!!! memset(pre,-1,sizeof(pre)); for(int i=0;i<MAXV;i++) dist[i]=INF; int h=0,t=1; q[h]=S; dist[S]=0; inQueue[S]=true; while(h<t) { int u=q[h++]; inQueue[u]=false; for(int p=head[u];p!=-1;p=edges[p].next) { int v=edges[p].v; if(dist[u]+edges[p].w<dist[v]&&edges[p].cap) { dist[v]=dist[u]+edges[p].w; pre[v]=p; if(!inQueue[v]) { inQueue[v]=true; q[t++]=v; } } } } return pre[T]!=-1; } double MCMF() { double cost=0; while(SPFA()) { if(dist[T]>=INF) break; int flow=INF; for(int p=pre[T];p!=-1;p=pre[edges[p].u]) flow=min(flow,edges[p].cap); for(int p=pre[T];p!=-1;p=pre[edges[p].u]) { edges[p].cap-=flow; edges[p^1].cap+=flow; } cost+=flow*dist[T]; } return cost; } struct Point { double x,y; }white[MAXV],black[MAXV]; double eucliddistance(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int ans[MAXV]; int main() { int n; while(scanf("%d",&n)!=EOF) { memset(head,-1,sizeof(head)); nCount=1; S=MAXV-2,T=MAXV-1; for(int i=1;i<=n;i++) { add(S,i,1,0); add(i+n,T,1,0); } for(int i=1;i<=n;i++) scanf("%lf%lf",&white[i].x,&white[i].y); for(int i=1;i<=n;i++) scanf("%lf%lf",&black[i].x,&black[i].y); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) add(i,j+n,1,eucliddistance(white[i],black[j])); //!!!!!! MCMF(); for(int i=1;i<=n;i++) for(int j=head[i];j!=-1;j=edges[j].next) { if(!edges[j].cap&&edges[j].v>n) { ans[i]=edges[j].v-n; break; } } for(int i=1;i<=n;i++) printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- [省选前题目整理][BZOJ 1059][ZJOI 2007]矩阵游戏(二分图最大匹配)
- [省选前题目整理][BZOJ 3140][HNOI 2013]消毒(二分图最大匹配)
- LA4043 - Ants(二分图完备最佳匹配KM)
- [省选前题目整理][BZOJ 1565][NOI 2009]植物大战僵尸(最小割+最大权闭合子图建模)
- [省选前题目整理][SPOJ OPTM]Optimal Marks(最小割)
- 二分图最大匹配与最小路径覆盖(一些题目)
- UVALive 4043 Ants(二分图最佳完美匹配、KM)
- UVALive - 4043 Ants (二分图最大权匹配)
- [省选前题目整理][LA 2197]Paint the Roads(费用流)
- [省选前题目整理][BZOJ 1185][HNOI 2007]最小矩形覆盖(旋转卡壳)
- UVALive 4043 Ants(二分图最佳完美匹配、KM)
- LA - 4043 - Ants(二分图最佳完美匹配)
- UVaLive 4043 Ants(二分图最佳完美匹配、KM)
- UVALive 4043 Ants 蚂蚁(二分图最佳完美匹配,KM算法)
- 关于二分图的最大匹配(最小点覆盖)问题的资料整理
- POJ 3565 Ants(二分图最小权完备匹配)
- LA 4043 - Ants 求完美匹配
- [省选前题目整理][BZOJ 1486][HNOI 2009]最小圈(01分数规划)
- LA 4043 Ants (最佳完美匹配)
- NYOJ 题目239月老的难题(二分图最大匹配,邻接表)