room——费用流

链接:https://www.nowcoder.com/acm/contest/143/E
来源:牛客网
 

题目描述

Nowcoder University has 4n students and n dormitories ( Four students per dormitory). Students numbered from 1 to 4n.

And in the first year, the i-th dormitory 's students are (x1[i],x2[i],x3[i],x4[i]), now in the second year, Students need to decide who to live with.

In the second year, you get n tables such as (y1,y2,y3,y4) denote these four students want to live together.

Now you need to decide which dormitory everyone lives in to minimize the number of students who change dormitory.

输入描述:

The first line has one integer n.

Then there are n lines, each line has four integers (x1,x2,x3,x4) denote these four students live together in the first year

Then there are n lines, each line has four integers (y1,y2,y3,y4) denote these four students want to live together in the second year

输出描述:

Output the least number of students need to change dormitory.

示例1

输入

复制

2
1 2 3 4
5 6 7 8
4 6 7 8
1 2 3 5

输出

复制

2

说明

Just swap 4 and 5

备注:

1<=n<=100

1<=x1,x2,x3,x4,y1,y2,y3,y4<=4n

It's guaranteed that no student will live in more than one dormitories.

这道题看完数据这么小,还以为是贪心,然后我们几个人就疯狂地枚举情况找错误样例,企图暴力过去。哪有这么简单啊,因为要考虑的实在是多,可能也能写出来

正解是费用流(当时简直想不到啊)

扫描二维码关注公众号,回复: 2567269 查看本文章

思路就是:对两边是n与n的宿舍限定流量是1,费用是两个宿舍不一样的人的个数,进行建边,然后跑一遍最小费用流。(比赛时想不到啊。虽然赛后也是仔细想了想才知道的)

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
 
using namespace std;
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const ll mod=1e9+7;
const double eps=1e-5;
const int maxm=1e2+10,maxn=5e4+7;
int T,k,m,n,N;
 
struct Edge{
    int to,next,cap,flow,cost;
}edge[maxn];
int tol,head[maxn],pre[maxn],dis[maxn];
bool vis[maxn];
void init()
{
    tol=0,mem(head,-1);
}
void addedge(int u,int v,int cap,int cost)
{
    edge[tol].to=v;edge[tol].cap=cap;edge[tol].cost=cost;
    edge[tol].flow=0;edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=0;edge[tol].cost=-cost;
    edge[tol].next=head[v];edge[tol].flow=0;head[v]=tol++;
}
bool spfa(int s,int t)
{
    queue<int>q;
    for(int i=0;i<N;i++)
        dis[i]=INF,vis[i]=false,pre[i]=-1;
    dis[s]=0,vis[s]=true,q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=false;
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
                dis[v]=dis[u]+edge[i].cost;
                pre[v]=i;
                if(!vis[v])
                    vis[v]=true,q.push(v);
            }
        }
    }
    if(pre[t]==-1) return false;
    return true;
}
int mincostmaxflow(int s,int t,int &cost)
{
    int flow=0;
    cost=0;
    while(spfa(s,t)){
        int Min=INF;
        for(int i=pre[t];~i;i=pre[edge[i^1].to])
            if(Min>edge[i].cap-edge[i].flow)
                Min=edge[i].cap-edge[i].flow;
        for(int i=pre[t];~i;i=pre[edge[i^1].to])
            edge[i].flow+=Min,edge[i^1].flow-=Min,cost+=edge[i].cost*Min;
        flow+=Min;
    }
    return flow;
}
 
struct node{
    int num[4];
};
node a[maxn],b[maxn];
 
int main()
{
    scanf("%d",&n);
    init();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<4;j++){
            scanf("%d",&a[i].num[j]);
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<4;j++){
            scanf("%d",&b[i].num[j]);
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            int v=0;
            for(int k=0;k<4;k++)
            {
                for(int p=0;p<4;p++)
                {
                    if(a[i].num[k]==b[j].num[p]) 
                        v++;
                    addedge(i+1,n+j+1,1,4-v);
                }
            }
        }
    }
    for(int i=0;i<n;i++)
        addedge(0,i+1,1,1),addedge(n+i+1,n*2+1,1,1);
    int ans;
    N=n*2+2;
    mincostmaxflow(0,n*2+1,ans);
    printf("%d\n",ans-n*2);
 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xianpingping/article/details/81368370
今日推荐