bzoj2539: [Ctsc2000]丘比特的烦恼

Posted AKCqhzdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2539: [Ctsc2000]丘比特的烦恼相关的知识,希望对你有一定的参考价值。

KM(带权二分图匹配)的裸题,就是构图和细节恶心。。

感觉今天一直在搞二分图匹配。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
map<string,int>mp;
char ss[10];
void Rose_max()
{
    int len=strlen(ss);
    for(int i=0;i<len;i++)
        if(A<=ss[i]&&ss[i]<=Z)ss[i]=ss[i]-A+a;
}
struct people
{
    int x,y;
}p[110];
bool v[110][110];

//----------------------

int n;
int love[110][110];
int exg[110],exb[110];
bool vg[110],vb[110];
int match[110],need[110];
bool findboy(int x)
{
    vg[x]=true;
    for(int i=1;i<=n;i++)
    {
        if(vb[i]==false)
        {
            int gap=exg[x]+exb[i]-love[x][i];
            if(gap==0)
            {
                vb[i]=true;
                if(match[i]==0||findboy(match[i])==true)
                {
                    match[i]=x;
                    return true;
                }
            }
            else need[i]=min(need[i],gap);
        }
    }
    return false;
}
void KM()
{
    memset(match,0,sizeof(match));
    memset(exb,0,sizeof(exb));
    for(int i=1;i<=n;i++)
    {
        exg[i]=0;
        for(int j=1;j<=n;j++)
            exg[i]=max(exg[i],love[i][j]);
    }//init
    
    for(int i=1;i<=n;i++)
    {
        memset(need,63,sizeof(need));
        while(1)
        {
            memset(vg,false,sizeof(vg));
            memset(vb,false,sizeof(vb));
            if(findboy(i)==true)break;
            
            int d=2147483647;
            for(int j=1;j<=n;j++)
                if(vb[j]==false)d=min(d,need[j]);
            for(int j=1;j<=n;j++)
            {
                if(vg[j]==true)exg[j]-=d;
                if(vb[j]==true)exb[j]+=d;
                else need[j]-=d;
            }
        }
    }
    
    int ans=0;
    for(int i=1;i<=n;i++)
        ans+=love[match[i]][i];
    printf("%d\n",ans);
}

//-----------KM--------------------------

int main()
{
    freopen("cupid.in","r",stdin);
    freopen("cupid.out","w",stdout);
    int K,x,y;
    scanf("%d%d",&K,&n);
    for(int i=1;i<=2*n;i++)
    {
        scanf("%d%d",&p[i].x,&p[i].y);
        memset(ss,0,sizeof(ss));scanf("%s",ss);Rose_max();
        mp[ss]=i;
    }
    
    for(int i=1;i<=n;i++)
        for(int j=n+1;j<=2*n;j++)
            if((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)<=K*K)
            {
                v[i][j]=true;
                for(int k=1;k<=n*2;k++)
                {
                    if(k!=i&&k!=j)
                    {
                        int x1=p[i].x,y1=p[i].y,x2=p[j].x,y2=p[j].y,x3=p[k].x,y3=p[k].y;
                        if(((x1<=x3&&x3<=x2)||(x1>=x3&&x3>=x2))&&((y1<=y3&&y3<=y2)||(y1>=y3&&y3>=y2)))
                            if((y3-y1)*(x3-x2)==(y3-y2)*(x3-x1))
                                {v[i][j]=false;break;}
                    }
                }
            }
    
    memset(love,-63,sizeof(love));
    for(int i=1;i<=n;i++)
        for(int j=n+1;j<=2*n;j++)    
            if(v[i][j]==true)love[i][j-n]=1;
    while(1)
    {
        memset(ss,0,sizeof(ss));scanf("%s",ss);Rose_max();
        if(ss[0]==e&&ss[1]==n&&ss[2]==d&&strlen(ss)==3)break;
        int p1=mp[ss];
        
        memset(ss,0,sizeof(ss));scanf("%s",ss);Rose_max();
        int p2=mp[ss];
        if(p2<=n)swap(p1,p2);
        
        scanf("%d",&x);
        if(v[p1][p2]==true)love[p1][p2-n]=x;
    }
            
    //------init------------
    
    KM();
    return 0;
}

以上是关于bzoj2539: [Ctsc2000]丘比特的烦恼的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2539: [Ctsc2000]丘比特的烦恼

bzoj2539 丘比特的烦恼黑书P333 (最优二分图匹配)

BZOJ 2541: [Ctsc2000]冰原探险

BZOJ2306 [Ctsc2011]幸福路径

图论(KM算法):COGS 290. [CTSC2008] 丘比特的烦恼

BZOJ 3555: [Ctsc2014]企鹅QQ