UVa1411-Ants
2015-10-29 19:34
381 查看
我有话说:
这道题是KM算法的一个非常巧妙的应用。对图上的的黑点和白点(数量相等)进行二分图最佳完美匹配,最后得到的最大权值即答案。为什么呢?
我们看假设图中a1-b1和a2-b2相交,那么dist(a1,b1)+dist(a2,b2)>dist(a1,b2)+dist(a2,b1);
所以我们求所有点对之间的距离最小值就可以了。最小值?不是说要求最大权值吗?加个负号就好了。
这道题是KM算法的一个非常巧妙的应用。对图上的的黑点和白点(数量相等)进行二分图最佳完美匹配,最后得到的最大权值即答案。为什么呢?
我们看假设图中a1-b1和a2-b2相交,那么dist(a1,b1)+dist(a2,b2)>dist(a1,b2)+dist(a2,b1);
所以我们求所有点对之间的距离最小值就可以了。最小值?不是说要求最大权值吗?加个负号就好了。
#include<cstring> #include<sstream> #include<vector> #include<algorithm> #include<queue> #include<cstdio> #include<cmath> using namespace std; const int maxn=100+10; const double INF=1e30; const double eps=1e-9; int n; bool S[maxn],T[maxn]; double Lx[maxn],Ly[maxn]; int left[maxn]; double W[maxn][maxn]; bool match(int i) { S[i]=1; for(int j=1;j<=n;j++)if(fabs(Lx[i]+Ly[j]-W[i][j])<1e-9&&!T[j]){ T[j]=1; if(!left[j]||match(left[j])){ left[j]=i; return true; } } return false; } void update() { double a=INF; for(int i=1;i<=n;i++)if(S[i]) for(int j=1;j<=n;j++)if(!T[j]) a=min(a,Lx[i]+Ly[j]-W[i][j]); for(int i=1;i<=n;i++){ if(S[i])Lx[i]-=a; if(T[i])Ly[i]+=a; } } void KM() { for(int i=1;i<=n;i++){ Lx[i]=Ly[i]=left[i]=0; for(int j=1;j<=n;j++){ Lx[i]=max(Lx[i],W[i][j]); } } for(int i=1;i<=n;i++){ for(;;){ for(int j=1;j<=n;j++)S[j]=T[j]=0; if(match(i))break; else update(); } } } int main() { int kase=0; while(scanf("%d",&n)==1){ if(++kase>1)printf("\n"); double x1[maxn],x2[maxn],y1[maxn],y2[maxn]; for(int i=1;i<=n;i++)scanf("%lf%lf",&x1[i],&y1[i]); for(int i=1;i<=n;i++)scanf("%lf%lf",&x2[i],&y2[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) W[j][i]=-sqrt((double)(x1[i]-x2[j])*(x1[i]-x2[j])+(double)(y1[i]-y2[j])*(y1[i]-y2[j])); KM(); for(int i=1;i<=n;i++)printf("%d\n",left[i]); } return 0; }
相关文章推荐
- android在代码中设置Spinner默认选中的值
- eclipse设置黑色主题
- tomcat 配置内存
- 内核优化
- 一个数组a[0...n-1],求a[j]-a[i]的最大值,其中i<j
- linux kvm 创建虚拟机
- android在代码中怎么设置 RadioGroup的默认值
- Junit
- 对于代码,越害怕写错就越写不敢写,然而带来的很明显是技术的滞留...
- UIDevice
- SQL基础
- 图像的锐化和边缘提取
- MySQL怎样存储IP地址
- VoIPER测试工具的使用
- coderforce 586A Alena's Schedule
- JavaScript常用方法函数收集
- Kindle 转换器
- arcEngine添加标注(上)
- LeetCode 213: House Robber II
- C++primer学习:关于upper_bound和lower_bound的探究.