5910. 【NOIP2018模拟10.18】DuLiu(瞎搞)

题目大意:

具体来说,这N道题每题都有一个毒瘤值,它们构成了一个序列。李Fee心目中有一个理想的毒瘤值序列,这个序列并不一定每一题的毒瘤值都是原本N道题中出现的,所以李Fee准备进行一些改动。这些改动体现在毒瘤值上就是将某道题的毒瘤值改为所有题的毒瘤值的二进制异或值。但是,改动题目是很麻烦的,他想算出最少需要多少次改动才能将原本的毒瘤值序列改成理想的毒瘤值序列,李Fee忙于出毒瘤题,他想请发明O(1/n)算法用暴力搜过所有毒瘤题的你帮他算出答案。但是他是个奸商,所以他并不打算给你报酬。

思路:

先把a,b的异或和求出来,然后排序判断是否全部相同,不同说明不合法。
然后在原序列中的ab不同的位置连边,每个联通快要联通快边数来操作,每次跳一个联通快要一的代价。如果a的异或和在b中不存在要把a的异或和当成大小为0的联通快。
可以证明每个联通块存在哈密顿回路。

程序:

#include
#include
#include

using namespace std;
const int N=100005;
const int inf=2*10e9;
int n,a[N],b[N],x,y,o,ans;

int main(){
	freopen("duliu.in","r",stdin);
	freopen("duliu.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]),x=x^a[i];
	for (int i=1;i<=n;i++) scanf("%d",&b[i]);
	for (int i=1;i<=n;i++) 
		if (a[i]==b[i]) {
			a[i]=inf;
			b[i]=inf;
		} else ans++;
	sort(a+1,a+n+1);
	sort(b+1,b+n+1);
	for (int i=1;i<=n;i++)
	if (a[i]!=b[i]) {
		y=b[i];
		o++;
	}
	if (o>=2) printf("-1\n");
	if (o==1&&y!=x) printf("-1\n");
	if (o==1&&y==x) printf("%d\n",ans);
	if (o==0&&ans!=0) printf("%d\n",ans+1);
	if (o==0&&ans==0) printf("0\n");
}

你可能感兴趣的:(找规律,听说瞎搞,图得连通性)