poj3565 ants

/*
km 最小權匹配 左邊是樹,右邊是螞蟻
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define MAXN 105
#define inf 999999999.0
#define eps 1e-5
struct Point
{
    double x;
    double y;
};
Point tree[MAXN],ant[MAXN];
double w[MAXN][MAXN];
double lx[MAXN],ly[MAXN];//期望
int link[MAXN];//匹配
int visx[MAXN],visy[MAXN];//是否已經匹配
double slack[MAXN];//匹配最小值
int n;

double dist(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int dfs(int x)
{
    visx[x]=1;
    for(int y=1;y<=n;y++)
    {
        if(visy[y]) continue;
        //如果y滿足匹配的條件
        double t=lx[x]+ly[y]-w[x][y];
        if(fabs(t)<eps)
        {
            visy[y]=1;
            //如果y沒有匹配或者y匹配的那位可以另找其它的y
            if(link[y]==-1||dfs(link[y]))
            {
                link[y]=x;
                return 1;
            }
        }
        else if(slack[y]>t)
            slack[y]=t;
    }
    return 0;
}

void KM()
{
    int i,j;
    memset(link,-1,sizeof(link));
    memset(ly,0,sizeof(ly));
    for(i=1;i<=n;i++)
    {
        lx[i]=-inf;
        for(j=1;j<=n;j++)
            if(w[i][j]>lx[i])
                lx[i]=w[i][j];
    }
    for(int x=1;x<=n;x++)
    {
        for(i=1;i<=n;i++)
            slack[i]=inf;
        while(1)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));

            //如果匹配成功,退出
            if(dfs(x)) break;

            //找到沒有匹配過的最小的匹配值
            double d=inf;
            for(i=1;i<=n;i++)
                if(!visy[i]&&d>slack[i])
                    d=slack[i];

            //這一輪參與的x的期望值減去d
            for(i=1;i<=n;i++)
                if(visx[i])
                    lx[i]-=d;

            //這一輪參與的y的期望值增加d
            for(i=1;i<=n;i++)
                if(visy[i])
                    ly[i]+=d;
                else
                    slack[i]-=d;

        }
    }
}

int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++)
        cin>>ant[i].x>>ant[i].y;
    for(i=1;i<=n;i++)
        cin>>tree[i].x>>tree[i].y;
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            w[i][j]=-dist(tree[i],ant[j]);
    KM();
    for(i=1;i<=n;i++)
        cout<<link[i]<<endl;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章