Gym 100273A Ants
来源:互联网 发布:trpg知乎 编辑:程序博客网 时间:2024/05/16 04:04
Gym 100273A Ants
二分图最大完美匹配
题意
给出n个蚁群与n个苹果树坐标(任意三点不共线),使得每一个蚁群对应一个苹果树,且蚁群到苹果树的路线不相交。保证有解,求总距离最短的方案。
思路
二分图最大(小)匹配,将权值变为负的来处理最小匹配,别忘了初始化也要初始化成负无穷。
容易想到完美匹配模型。
然后考虑路线相交的问题。对于四个定点,构成的两条不共点的线段。相交线段长度之和一定大于不相交的长度之和。
对于每条边的权值,另其等于两点的距离。那么问题转化为求最佳匹配(权值最小)。
由于KM算法一般是求权值最大的最佳匹配,因此套用KM算法时,可以让权值变为负值,这样问题转化为求权值最大的最佳匹配。
注意问题要输出的是蚁群所连接的苹果树编号。
那么匹配的时候,应该枚举每个苹果树,为其寻找匹配的蚁群。即L记录的是蚁群对应的苹果树编号。
大概就是熟悉一下板子。
余勇的板子感觉好复杂,不过比我在网上找的快一些。
代码
余勇的板子
#include<bits/stdc++.h>#include<stdlib.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN=107;const int oo=0x3f3f3f3f;typedef long long LL;double w[MAXN][MAXN], x[MAXN], slack[MAXN], y[MAXN];int prev_x[MAXN], prev_y[MAXN], son_y[MAXN], par[MAXN];int lx, ly, pop;///w表示带权图///pop表示一侧点数///返回最大完美匹配权值///son_y表示匹配方案void adjust(int v){ son_y[v]=prev_y[v]; if(prev_x[son_y[v]]!=-2) adjust(prev_x[son_y[v]]);}bool fin_d(int v){ for(int i=1;i<=pop;i++) { if(prev_y[i]==-1) { if(slack[i]>x[v]+y[i]-w[v][i]) { slack[i]=x[v]+y[i]-w[v][i]; par[i]=v; } if(x[v]+y[i]==w[v][i]) { prev_y[i]=v; if(son_y[i]==-1) { adjust(i); return true; } if(prev_x[son_y[i]]!=-1) continue; prev_x[son_y[i]]=i; if(fin_d(son_y[i])) return true; } } } return false;}int km(){ double m=-oo; for(int i=1;i<=pop;i++) { son_y[i]=-1; y[i]=0; } for(int i=1;i<=pop;i++) { x[i]=-oo; for(int j=1;j<=pop;j++) x[i]=max(x[i], w[i][j]); } bool flag; for(int i=1;i<=pop;i++) { for(int j=1;j<=pop;j++) { prev_x[j]=prev_y[j]=-1; slack[j]=oo; } prev_x[i]=-2; if(fin_d(i)) continue; flag=false; while(!flag) { m=oo; for(int j=1;j<=pop;j++) { if(prev_y[j]==-1) m=min(m, slack[j]); } for(int j=1;j<=pop;j++) { if(prev_x[j]!=-1) x[j]-=m; if(prev_y[j]!=-1) y[j]+=m; else slack[j]-=m; } for(int j=1;j<=pop;j++) { if(prev_y[j]==-1&&!slack[j]) { prev_y[j]=par[j]; if(son_y[j]==-1) { adjust(j); flag=true; break; } prev_x[son_y[j]]=j; if(fin_d(son_y[j])) { flag=true; break; } } } } } int ans=0; for(int i=1;i<=pop;i++) ans+=w[son_y[i]][i]; return ans;}LL px[MAXN], py[MAXN];double getDis(int i, LL d1, LL d2){ return sqrt(((double)px[i]-(double)d1)*((double)px[i]-(double)d1)+ ((double)py[i]-(double)d2)*((double)py[i]-(double)d2));}int main(){ freopen("ants.in", "r", stdin); freopen("ants.out", "w", stdout); memset(w, 0, sizeof(w)); int n;scanf("%d", &n); for(int i=1;i<=n;i++) { scanf("%I64d %I64d", &px[i], &py[i]); } for(int i=1;i<=n;i++) { LL ta, tb;scanf("%I64d %I64d", &ta, &tb); for(int j=1;j<=n;j++) { w[i][j]=-getDis(j, ta, tb); } } pop=n; km(); for(int i=1;i<=n;i++) printf("%d\n", son_y[i]); return 0;}
其他一个板子
#include<bits/stdc++.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN=107;const double eps=1e-10;const double oo=1e9;typedef long long LL;///W表示带权图///psum表示一侧点数///返回最大完美匹配权值///son_y表示匹配方案double W[MAXN][MAXN], Lx[MAXN], Ly[MAXN], slack[MAXN];int L[MAXN], psum;bool S[MAXN], T[MAXN];bool match(int u){ S[u]=true; for(int j=1; j<=psum; ++j) if(!T[j]) { if((Lx[u]+Ly[j]-W[u][j])<eps) { T[j]=true; if(!L[j]||match(L[j])) { L[j]=u; return true; } } else slack[j]=min(slack[j], Lx[u]+Ly[j]-W[u][j]); } return false;}LL KM(){ for(int i=1; i<=psum; ++i) { L[i]=Ly[i]=0; Lx[i]=-oo; for(int j=1; j<=psum; ++j) Lx[i]=max(Lx[i], W[i][j]); } for(int i=1; i<=psum; ++i) { for(int j=1; j<=psum; ++j) slack[j]=oo; while(1) { for(int j=1; j<=psum; ++j) S[j]=T[j]=0; if(match(i)) break; double a=oo; for(int j=1; j<=psum; ++j) if(!T[j]) a=min(a, slack[j]); for(int j=1; j<=psum; ++j) { if(S[j]) Lx[j]-=a; if(T[j]) Ly[j]+=a; } } } LL ans=0; /*for(int i=1;i<=psum;i++) { ans+=W[L[i]][i]; }*/ return ans;}double px[MAXN], py[MAXN];double qx[MAXN], qy[MAXN];int main(){ freopen("ants.in", "r", stdin); freopen("ants.out", "w", stdout); int n; while(scanf("%d", &n)==1) { memset(W, 0, sizeof(W)); for(int i=1;i<=n;i++) scanf("%lf %lf", &px[i], &py[i]); for(int i=1;i<=n;i++) scanf("%lf %lf", &qx[i], &qy[i]); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { W[i][j]=-sqrt((qx[i]-px[j])*(qx[i]-px[j])+(qy[i]-py[j])*(qy[i]-py[j])); } } psum=n; KM(); for(int i=1;i<=n;i++) printf("%d\n", L[i]); } return 0;}
阅读全文
0 0
- Gym 100273A Ants
- [agc013c]Ants on a Circle
- Gym 100015A
- codeforces gym 100645A
- CodeForces Gym 100803A
- Gym 100543A Parades
- Gym 100962A ABBA
- codeforces Gym 101102A
- Codeforces Gym 100372A
- 【Codeforces Gym 100187A】
- Gym 101147.A
- Ants
- Ants
- Ants
- Ants
- Ants
- Ants
- Ants
- 图像分辨率速查表
- pat 1110----C++的字符串不行啊
- ConfigReader(三十六)—— ReadMapObjConfig
- 机器学习历史
- 2017
- Gym 100273A Ants
- 002_跨平台开发_MUI_认识第一个MUI程序
- 类和对象(this指针、默认成员函数及运算符的重载)
- Java垃圾收集器
- Oracle树结构查询
- 海量数据优化的一些经验
- db-link创建过程
- 剑指offer-连续子数组的最大和
- tomcat和weblogic设置session有效期和tomcat应用访问权限