2018牛客多校五 room (最小费用最大流)

https://www.nowcoder.com/acm/contest/143/E

题意:有n个寝室,每个寝室有四个人,给你第一年和第二年住在一个寝室的人,问要让第一年变成第二年的样子最少需要多少学生换。

思路:把一个寝室当成两个点来看,分别为第一年和第二年的,然后暴力跑每个寝室这两年的学生不一样的个数乘2当做费用,然后用最小费用最大流做

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
struct edge
{
    int from,to,cap,flow,cost;
    edge(int u,int v,int c,int f,int co):
    from(u),to(v),cap(c),flow(f),cost(co){};
};
int n,s,t;
vector<int>g[maxn];
vector<edge>e;
void addedge(int u,int v,int c,int cost)
{
    e.push_back(edge(u,v,c,0,cost));
    e.push_back(edge(v,u,0,0,-cost));
    int zz=e.size();
    g[u].push_back(zz-2);
    g[v].push_back(zz-1);
}
int cost;
void init(int N)
{
    cost=0;
    for(int i=0;i<=N;i++)
    {
        g[i].clear();
    }
    e.clear();
}
int dis[maxn],pre[maxn],vis[maxn];
bool spfa()
{
      queue<int>q;
    for(int i=0;i<=t;i++)dis[i]=inf,pre[i]=0;
    dis[s]=0;
    memset(vis,0,sizeof(vis));
    vis[s]=1;
    q.push(s);
    int a=inf;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=0;i<g[u].size();i++)
        {
            edge f=e[g[u][i]];
            if(f.cap>f.flow&&dis[f.to]>dis[u]+f.cost)
            {
                dis[f.to]=dis[u]+f.cost;
                pre[f.to]=g[u][i];
                a=min(a,f.cap-f.flow);
                if(!vis[f.to])
                {
                    vis[f.to]=1;
                    q.push(f.to);
                }
            }
        }
    }
    if(dis[t]==inf)return 0;
    int u=t;
    cost+=dis[t]*a;
    while(u!=s)
    {
        e[pre[u]].flow+=a;
        e[pre[u]^1].flow-=a;
        u=e[pre[u]].from;
    }
    return 1;
}
void mincost()
{
    while(spfa())
    {
        continue;
    }
}
int x[150][5],y[150][5];
int main()
{
    scanf("%d",&n);
    init(2*n+2);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=4;j++)
        {
            scanf("%d",&x[i][j]);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=4;j++)
        {
            scanf("%d",&y[i][j]);
        }
    }
    s=0,t=2*n+1;
    for(int i=1;i<=n;i++)
        addedge(0,i,1,0);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int num=0;
            for(int a=1;a<=4;a++)
            {
                int f=0;
                for(int b=1;b<=4;b++)
                {
                    if(x[i][a]==y[j][b])
                    {
                        f=1;
                        break;
                    }
                }
                if(!f)num++;
            }
            addedge(i,j+n,1,2*num);
        }
    }
    for(int i=1;i<=n;i++)
        addedge(i+n,2*n+1,1,0);
    mincost();
    printf("%d\n",cost/2);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81412558