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

题目描述 
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,2,3,4)->(1,2,3,5)权值为3。然后用KM算法找最大匹配边权。

   如果是最大流,以换宿舍的人作为费用的话,只需要求每个宿舍i和现在的宿舍j中有 多少个不同的人作为费用建边,流量为1,答案就是最大流时的总费用。

   如果是费用流,以不换宿舍的人建边的话,要使在原来宿舍的人越多的宿舍先不换宿舍,那么每个宿舍i和现在的宿舍j中有多少个相同的人,建边两种宿舍的费用就是 4-相同的人数 ,流量为1。答案就是4*n+最大流的总费用。

代码:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define clear(A, X) memset(A, X, sizeof A)
#define min(A, B) ((A) < (B) ? (A) : (B))
using namespace std;

const int maxE = 2000000;
const int maxN = 256;
const int oo = 0x3f3f3f3f;

struct Edge{
    int v, c, w, n;
    Edge(){}
    Edge(int V, int C, int W, int N) : v(V), c(C), w(W), n(N){}
};

struct Node{
    int l, r, w;
};
struct poin
{
    int x,y;
}x1[300],x2[300];
Edge edge[maxE];
Node sche[maxN];
int adj[maxN], cntE;
int Q[maxE], head, tail;
int d[maxN], inq[maxN], cur[maxN], f[maxN];
int cost, flow, s, t;
int N, M, K;

void addedge(int u, int v, int c, int w){
    edge[cntE] = Edge(v, c,  w, adj[u]); adj[u] = cntE++;
    edge[cntE] = Edge(u, 0, -w, adj[v]); adj[v] = cntE++;
}

int spfa(){
    f[s] = oo;
    clear(d, oo);
    clear(inq, 0);
    cur[s] = -1;
    d[s] = 0;
    head = tail = 0;
    Q[tail++] = s;
    inq[s] = 1;
    while(head != tail){
        int u = Q[head++];
        inq[u] = 0;
        for(int i = adj[u]; ~i; i = edge[i].n){
            int v = edge[i].v, c = edge[i].c, w = edge[i].w;
            if(c && d[v] > d[u] + w){
                d[v] = d[u] + w;
                f[v] = min(f[u], c);
                cur[v] = i;
                if(!inq[v]){
                    Q[tail++] = v;
                    inq[v] = 1;
                }
            }
        }
    }
    if(d[t] == oo) return 0;
    flow += f[t];
    cost += d[t] * f[t];
    for(int i = cur[t]; ~i; i = cur[edge[i ^ 1].v]){
        edge[i].c -= f[t];
        edge[i ^ 1].c += f[t];
    }
    return 1;
}

int MCMF(){
    flow = cost = 0;
    while(spfa());
    return cost;
}

void init(){
    clear(adj, -1);
    cntE = 0;
}

int a[110][4];
int b[110][4];
int get(int x, int y) {
    int res = 0;
    for(int i=0;i<4;i++)
    for(int j=0;j<4;j++)
    if (a[x][i] == b[y][j]) res++;
    return res;
}
int S,T;
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)for(int j=0;j<4;j++)scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)for(int j=0;j<4;j++)scanf("%d",&b[i][j]);
    s=0;t=2*n+1;
    init();
    for(int i=1;i<=n;i++)
    {
        addedge(s, i, 1, 0);
        addedge(n + i, t, 1, 0);
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    addedge(i, n + j, 1, -get(i, j));
    cout << 4 * n + MCMF();
    return 0;
}
/*
2
1 2 3 4
5 6 7 8
4 6 7 8
1 2 3 5
*/
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联、自动化、电子信息等)的在学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值