poj3565 ants(KM)
2016-08-06 19:18
197 查看
题目链接:http://poj.org/problem?id=3565
题意: 有 N 个蚂蚁,N 个苹果,要在每个蚂蚁和一个相应的苹果之间连边,问如何给蚂蚁分配苹果,可以使这些边不相交。
分析:
应为在最小权值匹配的情况下满足没有边相交,可以简单证明,假设最小完备匹配中有两条线段AC和BD相交于点E,此时我们可以不连接AC和BD而去连接AD和BC,由于AE+DE>AD和BE+CE>BC,所有我们可以得出新连接的边的权值和一定比原来的边的权值和小,这样就可以得到一种权值和更小的匹配,这原来的匹配是最小带权和的匹配矛盾, 因此最小带权和的匹配中不会出现有两条线段相交的情况。KM算法是求最大权匹配问题,因此将此处的权值取距离的相反数即可。
源代码:
题意: 有 N 个蚂蚁,N 个苹果,要在每个蚂蚁和一个相应的苹果之间连边,问如何给蚂蚁分配苹果,可以使这些边不相交。
分析:
应为在最小权值匹配的情况下满足没有边相交,可以简单证明,假设最小完备匹配中有两条线段AC和BD相交于点E,此时我们可以不连接AC和BD而去连接AD和BC,由于AE+DE>AD和BE+CE>BC,所有我们可以得出新连接的边的权值和一定比原来的边的权值和小,这样就可以得到一种权值和更小的匹配,这原来的匹配是最小带权和的匹配矛盾, 因此最小带权和的匹配中不会出现有两条线段相交的情况。KM算法是求最大权匹配问题,因此将此处的权值取距离的相反数即可。
源代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double INF=9999999999.0; const double eps=1e-5; struct Node { double x,y; } ant[110],apple[110]; double dis(Node a,Node b) { return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } int nx,ny; bool visx[110],visy[110]; int linker[110]; double lx[110],ly[110]; double slack[110]; double mp[110][110]; bool dfs(int x) { visx[x]=true; for(int y=1; y<=ny; y++) { if(visy[y]) continue; double tmp=lx[x]+ly[y]-mp[x][y]; if(fabs(tmp)<eps) { visy[y]=true; if(linker[y]==-1 || dfs(linker[y])) { linker[y]=x; return true; } } else if(slack[y]>tmp) slack[y]=tmp; } return false; } void KM() { memset(linker,-1,sizeof linker); memset(ly,0,sizeof ly); for(int i=1; i<=nx; i++) { lx[i]=-INF; for(int j=1; j<=ny; j++) if(mp[i][j]>lx[i]) lx[i]=mp[i][j]; } for(int x=1; x<=nx; x++) { for(int i=1; i<=ny; i++) slack[i]=INF; while(1) { memset(visx,0,sizeof visx); memset(visy,0,sizeof visy); if(dfs(x)) break; double d=INF; for(int i=1; i<=ny; i++) if(!visy[i] && d>slack[i]) d=slack[i]; for(int i=1; i<=nx; i++) if(visx[i]) lx[i]-=d; for(int i=1; i<=ny; i++) { if(visy[i]) ly[i]+=d; else slack[i]-=d; } } } } int main() { int n; while(scanf("%d",&n)!=EOF) { for(int i=1; i<=n; i++) { scanf("%lf%lf",&ant[i].x,&ant[i].y); } for(int i=1; i<=n; i++) { scanf("%lf%lf",&apple[i].x,&apple[i].y); } for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { mp[i][j]=-dis(apple[i],ant[j]); } } nx=ny=n; KM(); for(int i=1;i<=ny;i++) printf("%d\n",linker[i]); } return 0; }
相关文章推荐
- poj3565 Ants(KM)
- 【KM】POJ3565[Ants]题解
- UVaLive 4043 Ants(二分图最佳完美匹配、KM)
- poj3565_KM不交叉边匹配
- POJ3565-Ants
- POJ 3565 Ants【KM】
- POJ3565 Ants【二分图最佳匹配】
- UVa 1411 Ants(KM)
- POJ 3565 Ants(计算几何,KM)
- 【UVA 1411】 Ants (KM)
- poj3565 Ants
- UVALive 4043 Ants(二分图最佳完美匹配、KM)
- LA4043 - Ants(二分图完备最佳匹配KM)
- LA4043 - Ants(二分图完备最佳匹配KM)
- POJ 3565 Ants (KM)
- poj 3565 Ants (KM)
- 弱校联萌十一大决战之厉兵秣马A ants【八皇后拓展】poj3565
- UVALive 4043 Ants(二分图最佳完美匹配、KM)
- ACM学习历程—POJ3565 Ants(最佳匹配KM算法)
- KM未能实施或实施不成功的4个原因