牛客多校(第五场)E room

将一个房间当做一个点,后来的房间与之前的房间中不用搬的人作为权值,建图,跑最大权匹配,就是不用搬的人数,在减一下即可,KM算法,O(n^3)

#include<cstring>
#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
#define N 200
#define INF 0x3f3f3f3f
int nx,ny;
int slack[N];
int match[N];
int mpt[N][N];
int lx[N],ly[N];
int sx[N],sy[N];
map <int,int> mp;
struct P
{
    int a,b,c,d;
}p[2*N];
int FindPath(int u)
{
    sx[u]=1;
    for(int v=1; v<=ny; v++)
    {
        int tmp=lx[u]+ly[v]-mpt[u][v];
        if(!sy[v] && tmp==0)
        {
            sy[v]=1;
            if(match[v]==-1 || FindPath(match[v]))
            {
                match[v]=u;
                return 1;
            }
        }
        else if(tmp<slack[v])
        {
            slack[v]=tmp;
        }
    }
    return 0;
}
int KM()
{
    int i,j,u;
    memset(match,-1,sizeof(match));
    for(i=1; i<=nx; i++)
    {
        lx[i]=-1;
        ly[i]=0;
        for(j=1; j<=ny; j++)
        {
            if(mpt[i][j]>lx[i]) lx[i]=mpt[i][j];
        }
    }
    for(u=1; u<=nx; u++)
    {
        for(i=1; i<=ny; i++)
        {
            slack[i]=INF;
        }
        while(1)
        {
            memset(sx,0,sizeof(sx));
            memset(sy,0,sizeof(sy));
            if(FindPath(u)) break;
            int dx=INF;
            for(i=1; i<=ny; i++)
            {
                if(!sy[i] && slack[i]<dx)
                    dx=slack[i];
            }

            for(i=1; i<=nx; i++)
            {
                if(sx[i]) lx[i]-=dx;
            }
            for(i=1; i<=ny; i++)
            {
                if(sy[i]) ly[i]+=dx;
                else slack[i]-=dx;
            }
        }
    }
    int sum=0;
    for(i=1; i<=ny; i++)
    {
        if(match[i]!=-1) sum+=mpt[match[i]][i];
    }
    return sum;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 1; i<=2*n; i++) scanf("%d%d%d%d",&p[i].a,&p[i].b,&p[i].c,&p[i].d);
    for(int i = 1; i<=n; i++){
        for(int j = 1; j<=n; j++){
            int e = 0;
            mp.clear();
            if(!mp[p[n+j].a]) mp[p[n+j].a]++; else e++;
            if(!mp[p[n+j].b]) mp[p[n+j].b]++; else e++;
            if(!mp[p[n+j].c]) mp[p[n+j].c]++; else e++;
            if(!mp[p[n+j].d]) mp[p[n+j].d]++; else e++;
            if(!mp[p[i].a]) mp[p[i].a]++; else e++;
            if(!mp[p[i].b]) mp[p[i].b]++; else e++;
            if(!mp[p[i].c]) mp[p[i].c]++; else e++;
            if(!mp[p[i].d]) mp[p[i].d]++; else e++;
            mpt[i][j] = e; //cout<<e<<endl;
        }
    }
    nx = ny = n;
    int ans = KM();
    printf("%d\n",n*4-ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41156122/article/details/81369014