ZJYYOJ 好基友(贪心/并查集)[C,C++]

题目及翻译

题面

每个班级总有几对好基友,创意班也不例外,最典型的就是汪李弟弟组合。现在有N对基友随机的坐在一排连续的座位上,好基友们总是希望能坐在一起,现在请你帮帮忙,计算一下最少要交换多少次(每两个人交换一次位置算作1次),以便让每对好基友都并肩坐在一起。
人的编号为 0 —— 2N - 1
座位的编号为 0 —— 2N - 1
每对好基友按照编号顺序来确定,(4,5)为好基友,(8,9)为好基友 , (0,1)为好基友

输入

样例输入由多组测试样例组成,第一行输入一个整数N(1 <= N <= 100000),代表有N对基友。第二行输入2N个整数,代表每个位置初始上的人编号

输出

输出最少交换次数

输入样例

2
0 2 1 3
2
3 2 0 1

输出样例

1
0

提示

第一组样例,我们只需要交换2 和 1即可
第二组样例,基友们本来就并肩而坐,不需要交换

题目思路

如果有人不匹配,一定是n对基友交错而排
把这样的n对基友视为一个集合那么每个集合都要交换n-1次

贪心思路

对于每个集合,每次都把集合内的其中一对基友匹配完毕,那么交换次数一定是n-1次
(剩下2对的时候只要交换1次)
把i和i+1视为一个沙发,id为x的人的好基友为x ^ 1(亦或)
只需要记录每个人的位置,把每一对不匹配的基友其中一个换到匹配的基友就行

并查集思路

默认相同的基友在同一个集合(1对基友也算一个集合,需要交换0次)
合并每个沙发上的两人,统计一下每个集合中的(基友对数-1)之和即可

注意事项

数据量很大,c++需要用ios::sync_with_stdio(false);来加速

AC代码

贪心代码

C/C++(几乎没有代码变更)

用时400MS 内存17804K 长度505B

#include<iostream>
using namespace std;
const int MAXN = 2e6;
int n;
int sofa[MAXN+10];
int pos[MAXN+10];
int main(){
	ios::sync_with_stdio(false);
	while(cin>>n){
		for(int i=0;i<2*n;++i){
			cin>>sofa[i];
			pos[sofa[i]] = i;//记录每个人的位置
		}
		int ans = 0;
		for(int i=0;i<2*n;i+=2){
			if((sofa[i] ^ 1) == sofa[i+1])continue;//如果是好基友则跳过
			int f1 = sofa[i+1];//记录错的人
			int f2 = sofa[i] ^ 1;//记录对的人
			swap(sofa[i+1],sofa[pos[sofa[i]^1]]);//把对的人和错的人的交换
			swap(pos[f1],pos[f2]);//把两人的位置交换
			++ans;
		}
		cout<<ans<<endl;
	}
	return 0;
}

Java

待更新~

并查集代码

C/C++(几乎没有代码变更)

用时692MS 内存3740K 长度591B

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5;
int n,a,b,ans;
int f[2*MAXN+10],cnt[2*MAXN+10];
int fd(int x){//裸find函数
	while(x != f[x])x = f[x];
	return x;
}
void mrg(int x,int y){//裸merge函数
	f[fd(x)] = fd(y);
}
int main(){
	ios::sync_with_stdio(false);
	while(cin>>n){
		memset(cnt,0,sizeof(cnt));
		for(int i=0;i<2*n;i+=2)f[i] = f[i+1] = i;//好基友在同一集合
		for(int i=0;i<n;++i){
			cin>>a>>b;
			mrg(a,b);//合并一个沙发上的两个人
		}
		ans = 0;
		for(int i=0;i<2*n;++i){
			++cnt[fd(i)];//统计每个集合的人数
		}
		for(int i=0;i<2*n;++i){
			if(cnt[i])ans += cnt[i] / 2 - 1;//统计答案 人数 / 2 - 1
		}
		cout<<ans<<endl;
	}
	return 0;
}


Java

待更新~

本文作者 CSDN@扶她小藜
个人主页链接 https://blog.csdn.net/weixin_44579869

发布了15 篇原创文章 · 获赞 2 · 访问量 724

猜你喜欢

转载自blog.csdn.net/weixin_44579869/article/details/104510827