题目描述
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.


题目要求我们找出最小的学生交换个数(我一直想成最小的交换次数QWQ)。。。。。


由于学生分别去哪个寝室是不定的,所以我们考虑使用最小费用流。因为只要学生有移动,那么必然对答案做出了贡献。所以我们需要知道现在的寝室到目标寝室需要交换的人的个数。set存一存就行了。

心有感慨,QWQ似乎在以前很菜(现在也菜)的时候碰到过这种题两次,然后GG了。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1010,M=1000010;
int n,x[N][4],y[N][4],v[N],e[N],s,t,d[N];
int head[N<<3],nex[M],to[M],w[M],flow[M],tot=1;
inline void ade(int a,int b,int c,int d){
	to[++tot]=b; w[tot]=d; flow[tot]=c; nex[tot]=head[a]; head[a]=tot;
} 
inline void add(int a,int b,int c,int d){
	ade(a,b,c,d);	ade(b,a,0,-d);
}
int spfa(){
	memset(d,0x3f,sizeof d);	queue<int> q;	q.push(s);
	int vis[N]={0};	vis[s]=1;	d[s]=0;
	while(q.size()){
		int u=q.front();	q.pop();	vis[u]=0;
		for(int i=head[u];i;i=nex[i]){
			if(flow[i]&&d[to[i]]>d[u]+w[i]){
				d[to[i]]=d[u]+w[i];
				v[to[i]]=u; e[to[i]]=i;
				if(!vis[to[i]])	q.push(to[i]),vis[to[i]]=1;
			}
		}
	} 
	return d[t]!=0x3f3f3f3f;
}
int EK(){
	int res=0;
	while(spfa()){
		int mi=0x3f3f3f3f;
		for(int i=t;i!=s;i=v[i])	mi=min(mi,flow[e[i]]);
		for(int i=t;i!=s;i=v[i])	flow[e[i]]-=mi,flow[e[i]^1]+=mi;
		res+=d[t]*mi;
	}
	return res;
}
signed main(){
	cin>>n;	s=0;	t=n*2+2;
	for(int i=1;i<=n;i++)	for(int j=0;j<4;j++)	cin>>x[i][j];
	for(int i=1;i<=n;i++)	for(int j=0;j<4;j++)	cin>>y[i][j];
	for(int i=1;i<=n;i++){
		add(s,i,1,0);
		for(int j=1;j<=n;j++){
			set<int> st;	st.clear();	int sum=0;
			for(int k=0;k<4;k++)	st.insert(x[i][k]);
			for(int k=0;k<4;k++)	if(st.count(y[j][k]))	sum++;
			add(i,j+n,1,4-sum);	
		}
		add(i+n,t,1,0);
	}
	cout<<EK()<<endl; 
	return 0;
}