• 2018牛客网暑期ACM多校训练营(第五场) E


    题目链接:https://www.nowcoder.com/acm/contest/143/E

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

    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.

    输入

    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.

    题意:

    现有n个宿舍,4n个学生,即一个宿舍四个学生,学生从1~4n编号,

    第一年,每个宿舍x1[i],x2[i],x3[i],x4[i]代表四个学生,

    现在第二年,有n张表,每张表上y1,y2,y3,y4代表该宿舍四个学生分别想和谁一起住,

    现在需要决策每个学生住哪个宿舍,使得换宿舍的学生数最少,输出这个数。

    题解:

    转化为最小费用最大流解决的二分图问题,对每个去年的宿舍,向每个今年的组合连一条边,权值为1,费用为需要搬的人数(4-相同的人数),源点到去年各点,今年各点到汇点,都连一条权值为1费用为0的最大流,跑一次费用流即可。(参考https://www.nowcoder.com/discuss/90015?type=101&order=0&pos=1&page=0

    说实话,第一次看到这题比较懵逼的,因为以为宿舍必须住四个人,但是看了题解之后,发现好像没有规定宿舍住的人数。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=110;
    const int INF=0X3f3f3f3f;
    
    struct Edge{
        int u,v,c,f,a;
    };
    struct MCMF
    {
        int s,t;
        vector<Edge> E;
        vector<int> G[2*maxn];
        int vis[2*maxn];
        int d[2*maxn];
        int pre[2*maxn];
        int aug[2*maxn];
        void init(int l,int r)
        {
            for(int i=l;i<=r;i++) G[i].clear();
            E.clear();
        }
        void addedge(int from,int to,int cap,int cost)
        {
            E.push_back((Edge){from,to,cap,0,cost});
            E.push_back((Edge){to,from,0,0,-cost});
            int m=E.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
        bool SPFA(int s,int t,int &flow,int &cost)
        {
            memset(d,INF,sizeof(d));
            memset(vis,0,sizeof(vis));
            d[s]=0, vis[s]=1, pre[s]=0, aug[s]=INF;
            queue<int> q;
            q.push(s);
            while(!q.empty())
            {
                int now=q.front(); q.pop();
                vis[now]=0;
                for(int i=0;i<G[now].size();i++)
                {
                    Edge& e=E[G[now][i]];
                    int nex=e.v;
                    if(e.c>e.f && d[nex]>d[now]+e.a)
                    {
                        d[nex]=d[now]+e.a;
                        pre[nex]=G[now][i];
                        aug[nex]=min(aug[now],e.c-e.f);
                        if(!vis[nex])
                        {
                            q.push(nex);
                            vis[nex]=1;
                        }
                    }
                }
            }
            if(d[t]==INF) return 0;
            flow+=aug[t];
            cost+=d[t]*aug[t];
            for(int i=t;i!=s;i=E[pre[i]].u)
            {
                E[pre[i]].f+=aug[t];
                E[pre[i]^1].f-=aug[t];
            }
            return 1;
        }
    
        int mincost()
        {
            int flow=0,cost=0;
            while(SPFA(s,t,flow,cost));
            return cost;
        }
    }mcmf;
    
    int n;
    struct Dorm{
        int x[4];
    }fst[maxn],snd[maxn];
    int cost(Dorm fst,Dorm snd)
    {
        int res=4;
        for(int i=0;i<4;i++)
        {
            bool stay=0;
            for(int j=0;j<4;j++) stay|=(fst.x[i]==snd.x[j]);
            res-=stay;
        }
        return res;
    }
    
    int main()
    {
        scanf("%d",&n);
        mcmf.init(0,2*n+1);
        mcmf.s=0, mcmf.t=2*n+1;
    
        for(int i=1;i<=n;i++) for(int k=0;k<4;k++) scanf("%d",&fst[i].x[k]);
        for(int i=1;i<=n;i++) for(int k=0;k<4;k++) scanf("%d",&snd[i].x[k]);
    
        for(int i=1;i<=n;i++)
        {
            mcmf.addedge(mcmf.s,i,1,0);
            mcmf.addedge(n+i,mcmf.t,1,0);
            for(int j=1;j<=n;j++) mcmf.addedge(i,n+j,1,cost(fst[i],snd[j]));
        }
    
        printf("%d
    ",mcmf.mincost());
    }
  • 相关阅读:
    设计模式——观察者模式
    安卓xml动画
    部署在weblogic上的springboot项目上传文件(servlet方式)
    Spring Boot 部署到weblogic 12c
    SpingBoot+Druid监控页面打不开(404)
    DAY49-前端入门-浮动布局案例、z-index、flex布局、响应式布局、过渡与动画
    DAY48-前端入门-文档流、浮动布局、清浮动、流式布局、定位布局
    DAY46-前端入门-组合选择器、标签a_img_list、盒模型、伪类、盒模型布局
    DAY45-前端入门-css的三种引用方式以及优先级、样式与长度颜色、常用样式、css选择器
    DAY44-前端入门-前端三剑客、第一个页面、常用标签、标签分类
  • 原文地址:https://www.cnblogs.com/dilthey/p/9420166.html
Copyright © 2020-2023  润新知