牛客网多校训练五 E-room

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy704599894/article/details/81367807

链接: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

题意:有n个宿舍,每个宿舍分别住有x1,x2,x3,x4,现有一个列表,每个表中有y1,y2,y3,y4,表示这四个学生想住在一起,请问如果满足了所有学生的要求,最少有几个学生需要搬宿舍。

最小费用最大流,将其分为n*2个节点,前n个节点表示当前宿舍情况,后n个节点表示目标宿舍情况,对于前n个节点的每个点都向后n个节点的每个点连一条边,流量为1,权值为xi->yj需要搬几名学生,源点连前n个节点,后n个节点连汇点,求一遍最小费用最大流即可。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
const int maxm = 500005;
const int INF = 1e9 + 7;
struct node
{
	int u, v, flow, cost, next;
}edge[maxm];
struct S
{
	int a[5];
}x[maxm];
int n, m, s, t, cnt, sum, FLOW;
int head[maxm], vis[maxm], dis[maxm], cur[maxm], pre[maxm];
void init()
{
	cnt = 0, s = 0, t = n + 1;
	memset(head, -1, sizeof(head));
}
void add(int u, int v, int flow, int cost)
{
	edge[cnt].u = u, edge[cnt].v = v;
	edge[cnt].flow = flow, edge[cnt].cost = cost;
	edge[cnt].next = head[u], head[u] = cnt++;
	edge[cnt].u = v, edge[cnt].v = u;
	edge[cnt].flow = 0, edge[cnt].cost = -cost;
	edge[cnt].next = head[v], head[v] = cnt++;
}
int bfs()
{
	queue<int>q;
	for (int i = 0;i <= t;i++) dis[i] = INF;
	memset(pre, -1, sizeof(pre));
	dis[s] = 0, q.push(s);
	int rev = 0;
	while (!q.empty())
	{
		int u = q.front();q.pop();
		for (int i = head[u];i != -1;i = edge[i].next)
		{
			int v = edge[i].v;
			if (dis[v] > dis[u] + edge[i].cost&&edge[i].flow)
			{
				dis[v] = dis[u] + edge[i].cost;
				pre[v] = i, q.push(v);
			}
		}
	}
	if (dis[t] == INF) return 0;
	return 1;
}
int MCMF()
{
	int ans = 0, minflow;
	while (bfs())
	{
		minflow = INF;
		for (int i = pre[t];i != -1;i = pre[edge[i].u])
			minflow = min(minflow, edge[i].flow);
		for (int i = pre[t];i != -1;i = pre[edge[i].u])
			edge[i].flow -= minflow, edge[i ^ 1].flow += minflow;
		ans += dis[t] * minflow;
	}
	return ans;
}
int main()
{
	int i, j, k;
	scanf("%d", &n);
	n *= 2;
	init();
	for (i = 1;i <= n/2;i++)
	{
		scanf("%d%d%d%d", &x[i].a[1], &x[i].a[2], &x[i].a[3], &x[i].a[4]);
		add(s, i, 1, 0);
	}
	for (i = n / 2 + 1;i <= n;i++)
	{
		scanf("%d%d%d%d", &x[i].a[1], &x[i].a[2], &x[i].a[3], &x[i].a[4]);
		for (j = 1;j <= n / 2;j++)
		{
			k = 0;
			for (int l = 1;l <= 4;l++)
				for (int r = 1;r <= 4;r++)
					if (x[j].a[l] == x[i].a[r])
						k++;
			add(j, i, 1, 4 - k);
		}
		add(i, t, 1, 0);
	}
	printf("%d\n", MCMF()); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zy704599894/article/details/81367807