题目大意:

给定\(n\)个蚂蚁和\(n\)颗苹果树的坐标,要求每个蚂蚁爬到一颗苹果树旁,使得每个蚂蚁路线不相交且路线总长度最小,求每个蚂蚁爬到哪个苹果树旁?

首先假设有两只蚂蚁路径相交,那么这两个蚂蚁交换目标一定使得总路线缩短且不相交,所以总长度最短时所有蚂蚁路线一定不相交

怎么让总路线最短呢?二分图最小权匹配

其实只要把边权全部取反然后跑最大权匹配就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
namespace red{
#define int long long
#define eps (1e-6)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=210;
int n;
struct node
{
int x,y;
}ant[N],tr[N];
double jx[N][N];
inline int sqr(int x){return x*x;}
inline double dis(int i,int j)
{
return sqrt(sqr(ant[i].x-tr[j].x)+sqr(ant[i].y-tr[j].y));
}
double exl[N],exr[N],slack[N];
bool visl[N],visr[N];
int f[N],g[N];
inline bool find(int x)
{
visl[x]=1;
for(int y=1;y<=n;++y)
{
if(visr[y]) continue;
double tmp=exl[x]+exr[y]-jx[x][y];
if(fabs(tmp)<eps)
{
visr[y]=1;
if(!f[y]||find(f[y]))
{
f[y]=x;
g[x]=y;
return 1;
}
}
else slack[y]=min(tmp,slack[y]);
}
return 0;
}
inline void km()
{
for(int i=1;i<=n;++i)
{
exl[i]=jx[i][1];
for(int j=2;j<=n;++j)
{
exl[i]=max(exl[i],jx[i][j]);
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
visl[j]=visr[j]=0;
slack[j]=1e9+7;
}
if(find(i)) continue;
while("haku")
{
double tmp=1e9+7;
int t;
for(int j=1;j<=n;++j)
if(!visr[j]) tmp=min(tmp,slack[j]);
for(int j=1;j<=n;++j)
{
if(visl[j]) exl[j]-=tmp;
if(visr[j]) exr[j]+=tmp;
else
{
slack[j]-=tmp;
if(fabs(slack[j])<eps) t=j;
}
}
if(!f[t]) break;
visr[t]=1,visl[f[t]]=1;
t=f[t];
for(int j=1;j<=n;++j)
slack[j]=min(slack[j],exl[t]+exr[j]-jx[t][j]);
}
memset(visl,0,sizeof(visl));
memset(visr,0,sizeof(visr));
find(i);
}
for(int i=1;i<=n;++i) printf("%lld\n",g[i]);
}
inline void main()
{
while(~scanf("%lld",&n))
{
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
memset(exl,0,sizeof(exl));
memset(exr,0,sizeof(exr));
for(int i=1;i<=n;++i)
{
ant[i].x=read(),ant[i].y=read();
}
for(int i=1;i<=n;++i)
{
tr[i].x=read(),tr[i].y=read();
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
jx[i][j]=-dis(i,j);
}
}
km();
} }
}
signed main()
{
red::main();
return 0;
}

最新文章

  1. 自动爬取ZiMuZu的内容发布到Wordpress
  2. GMM的EM算法实现
  3. MYSQL企业常用架构与调优经验分享
  4. 学习smali
  5. 基本上,把switch,用设计模式代替,肯定是bug和过度设计。想想,本来修改一个文件几行代码可以解决的问题,变成修改3-6个类才能实现一样的功能。不是傻是什么?
  6. 【python】原始字符创
  7. 【转】10款GitHub上最火爆的国产开源项目
  8. asp.net mvc项目远程发布到windows server服务器
  9. pt-align
  10. 题解-GXOI/GZOI2019 特技飞行
  11. Objective-C 事件响应链
  12. Jenkins进阶-用户权限管理(10)
  13. Nexus网页直接上传jar包
  14. bzoj4035【HAOI2015】数组游戏
  15. Linux 下搭建 Svn+Apache
  16. Hadoop案例(十一)MapReduce的API使用
  17. vim 将文件从dos格式转换到unix格式
  18. JVM反调调用优化,导致发生大量异常时log4j2线程阻塞
  19. delphi VCL研究之消息分发机制-delphi高手突破读书笔记
  20. PIE SDK文本元素的绘制

热门文章

  1. Jave正则的实现
  2. ngx ------ngx_cache_manager_process_cycle
  3. 打乱Map key - value的对应顺序
  4. HttpClient4.3 连接池参数配置及源码解读
  5. mysql case when语句的使用
  6. .NET 5 ORM 八大实用技巧 干货 - SqlSugar ORM
  7. 硕思logo设计师注册码去哪里找,文末附链接
  8. 攻克弹唱第八课(吉他演奏的律动与funk音乐)
  9. 苹果电脑下载器Folx有没有自动下载功能
  10. Lumen中启用session