bzoj2539

题解:

KM匹配

注意判断不能在一条直线上

然后大小写相同

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=4005;
map<string,int> MP;
float R,x[N],y[N];
int G[N][N],n,p,a,b,l[N],r[N],slack[N],con[N],vy[N],vx[N];
int on(int a,int b,int c)
{
    if (x[a]==x[b]&&x[b]==x[c])
     return (min(y[a],y[b])<=y[c]&&y[c]<=max(y[a],y[b]));
    return ((y[a]-y[b])*(x[c]-x[b])==(y[c]-y[b])*(x[a]-x[b]));
}
int Judge(int a,int b)
{
    if (x[a]>x[b]) swap(a,b);
    for (int i=1;i<=n*2;i++)
     if (i!=a&&i!=b&&x[a]<=x[i]&&x[i]<=x[b])
    if (on(a,b,i)) return 0;
    return 1;
}
float dis(int a,int b)
{
    return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
void Preoperate()
{
    memset(l,0,sizeof(l));
    for (int i=1;i<=2*n;i++)
     for (int j=1;j<=2*n;j++) l[i]=max(l[i],G[i][j]);
    memset(r,0,sizeof(r));
}
int find(int x)
{
    vx[x]=1;
    for (int i=n+1;i<=2*n;i++)
     if (!vy[i])
      {
        if (G[x][i]==l[x]+r[i])
         {
            vy[i]=1;
            if (con[i]==-1||find(con[i]))
             {
                con[i]=x;
                return 1;
             }
         }
        else slack[i]=min(slack[i],l[x]+r[i]-G[x][i]);
     }
    return 0;
}
int main()
{
    memset(G,-0x3f,sizeof(G));
    string str;
    scanf("%f%d",&R,&n);
    for (int i=1;i<=2*n;i++)
     {
        scanf("%f %f",&x[i],&y[i]);
        cin>>str;
        for (int j=0;j<str.length();j++)
         if (str[j]<='Z'&&str[j]>='A') str[j]+='a'-'A';
        MP[str]=i;
    }
    while (1)
     {
        cin>>str;
        if (str=="End") break;
        for (int i=0;i<str.length();i++)
         if (str[i]<='Z'&&str[i]>='A') str[i]+='a'-'A';
        a=MP[str];
        cin>>str;
        for (int i=0;i<str.length();i++) 
         if (str[i]<='Z'&&str[i]>='A') str[i]+='a'-'A';
        b=MP[str];
        scanf("%d",&p);
        if (a>b) swap(a,b);
        if (dis(a,b)<=R*R&&Judge(a,b)) G[a][b]=p;
     }
    for (int i=1;i<=n;i++)
     for (int j=n+1;j<=2*n;j++)
      if(G[i][j]<0&&dis(i,j)<=R*R&&Judge(i,j)) G[i][j]=1;
    Preoperate();
    memset(con,-1,sizeof(con));
    for (int j=1;j<=n;j++)
     {
        for (int k=1;k<=1000;k++)
         {
            memset(slack,127,sizeof(slack));
            memset(vx,0,sizeof(vx));
            memset(vy,0,sizeof(vy));
            if (find(j)) break;
            int d=2e9;
            for (int i=n+1;i<=n*2;i++)
             if (!vy[i]) d=min(d,slack[i]);
            for (int i=1;i<=n;i++)
             if(vx[i]) l[i]-=d;
            for (int i=n+1;i<=n*2;i++)
             if(vy[i]) r[i]+=d;
         }
     }
    int ans=0;
    for (int i=1;i<=n*2;i++)
     if (con[i]!=-1) ans+=G[con[i]][i];
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8297875.html