poj 3565 Ants

Problem Description

一个棋盘,有n个黑点和n个白点,求一种方案让黑白点两两配对且任意一对黑白点之间的连线不相交

思路:因为所有线段不相交,所以每条线段长度之和最小,因为必然有一种方案,所以是完全匹配,把点点间距离取反,跑一个KM最大带权匹配就好了

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N = 220;
const double eps = 1e-6;
const int INF = 1e9;
double g[N][N], la[N], lb[N], delta;
bool va[N], vb[N];
int n,mat[N],ans[N];
double dist(int x1,int y1,int x2,int y2){
    int tx = x1 - x2, ty = y1 - y2;
    return -sqrt(tx * tx + ty * ty);
}
bool che(double x){  return fabs(x) < eps;}
bool dfs(int x){
    va[x] = 1;
    for(int y = 1; y <= n; y++){
        if(!vb[y])
          if(che(la[x] + lb[y] - g[x][y])){
            vb[y] = 1;
            if(!mat[y] || dfs(mat[y])){
                mat[y] = x;
                return 1;
            }
          }
    }
    return 0;
}
void update() {  
    delta = 1e10;  
    for (int i = 1; i <= n; i ++) if (va[i]) {  
        for (int j = 1; j <= n; j ++) if (!vb[j]) {  
            delta = min(delta, la[i] + lb[j] - g[i][j]);  
        }  
    }  
    for (int i = 1; i <= n; i ++) {  
        la[i] -= va[i] ? delta : 0;  
        lb[i] += vb[i] ? delta : 0;  
    }  
}  
void KM(){
    for(int i = 1; i <= n; i++){
        la[i] = -INF; lb[i] = 0;
        for(int j = 1; j <= n; j++)
          la[i] = max(la[i],g[i][j]);
    }
    for(int i = 1; i <= n; i++)
      while(1){
        memset(va,0,sizeof(va));
        memset(vb,0,sizeof(vb));
        if(dfs(i)) break;
        update();
      }
    return ;
}
void init(){
    memset(g,0,sizeof(g));
    memset(la,0,sizeof(la));
    memset(lb,0,sizeof(lb));
    memset(ans,0,sizeof(ans));
}
int main(){
    ios::sync_with_stdio(false);
    double x[110], y[110];
    while(cin>>n){
        init();
        for(int i = 1; i <= n; i++)
          cin>>x[i]>>y[i];
            double xx,yy;
        for(int i = 1; i <= n; i++){
            cin>>xx>>yy;
            for(int j = 1; j <= n; j++)
              g[j][i] = dist(x[j],y[j],xx,yy);
        }
        KM();
        for(int i = 1; i <= n; i++)
          ans[mat[i]] = i;
        for(int i = 1; i <= n; i++)
          cout<<ans[i]<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Rorshach/p/8682989.html