【題解】Luogu UVA1411 Ants
阿新 • • 發佈:2018-12-08
原題傳送門
部落格裡對二分圖匹配的詳細介紹
這道題是帶權二分圖匹配
用的是KM演算法
我們要知道一個定理:要使線段沒有相交,要使距離總和最小
我們先把任意一對白點、黑點的距離算一下
然後運用KM演算法
因為要最小權值,所以需要把權值取反來求最大。
#include <bits/stdc++.h> #define N 105 using namespace std; inline void write(register int x) { if(!x)putchar('0');if(x<0)x=-x,putchar('-'); static int sta[25];int tot=0; while(x)sta[tot++]=x%10,x/=10; while(tot)putchar(sta[--tot]+48); } inline double Max(register double x,register double y) { return x>y?x:y; } inline double Min(register double x,register double y) { return x<y?x:y; } int n; double X1[N],Y1[N],X2[N],Y2[N]; double dis[N][N]; double lx[N],ly[N]; int link[N],s[N],t[N]; inline bool dfs(register int x) { s[x]=1; for(register int i=1;i<=n;++i) if(fabs(lx[x]+ly[i]-dis[x][i])<1e-9&&!t[i]) { t[i]=1; if(!link[i]||dfs(link[i])) { link[i]=x; return true; } } return false; } inline void update() { double a=23333333; for(register int i=1;i<=n;++i) if(s[i]) for(register int j=1;j<=n;++j) if(!t[j]) a=Min(a,lx[i]+ly[j]-dis[i][j]); for(register int i=1;i<=n;++i) { if(s[i]) lx[i]-=a; if(t[i]) ly[i]+=a; } } inline void KM() { for(register int i=1;i<=n;++i) { link[i]=lx[i]=ly[i]=0; for(register int j=1;j<=n;++j) lx[i]=Max(lx[i],dis[i][j]); } for(register int i=1;i<=n;++i) while(19260817) { for(register int j=1;j<=n;++j) s[j]=t[j]=0; if(dfs(i)) break; else update(); } } inline double getdis(register int x,register int y) { return sqrt(pow(X1[x]-X2[y],2)+pow(Y1[x]-Y2[y],2)); } int main() { while(scanf("%d",&n)!=EOF) { for(register int i=1;i<=n;++i) scanf("%lf %lf",&X1[i],&Y1[i]); for(register int i=1;i<=n;++i) scanf("%lf %lf",&X2[i],&Y2[i]); for(register int i=1;i<=n;++i) for(register int j=1;j<=n;++j) dis[j][i]=-getdis(i,j); KM(); for(register int i=1;i<=n;++i) write(link[i]),puts(""); } return 0; }