Bitwise Exclusive-OR Sequence

Bitwise Exclusive-OR Sequence

题意:

有n个点, m个关系 每个关系 a b c 表示点a的值 异或 点b的值,为c

分析

首先可能是多个图, 对于每个图中的每一位, 取0 或者取1 都是可以确定图上的其他数字取0 或者取1 。 所以我们可以去枚举取0 或者取1 ,来取个min 得到结果。
所以这里我们用并查集, 最大数为 2的30次, 所以我们对于每一位都做一个并查集, 就是30个并查集。 f[a] 表示当前位置取1 f[a+n] 表示当前位取0
这样就可以枚举区间了。

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

const int N = 2e5+10;

LL n, m, fa[N], sz[N];
LL a[N];

struct Node
{
	LL a, b;
	LL val;
}num[N];

LL find(LL x)
{
	if(fa[x] != x) fa[x] = find(fa[x]);
	return fa[x];
}


void init()
{
	for(LL i = 1; i <= n; i ++)
	{
		fa[i] = i, sz[i] = 1;
		fa[i+n] = i+n, sz[i+n] = 0;
	}
}

void merge(LL a, LL b)
{
	sz[a] += sz[b];
	fa[b] = a;
}

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= m; i ++)
	{
		scanf("%lld%lld%lld", &num[i].a, &num[i].b, &num[i].val);
	}
	
	LL res = 0;
	
	for(int i = 0; i < 30; i ++)
	{
		init(); // 每一次做并查集都要初始化!
		for(int j = 1; j <= m; j ++)
		{
			int aa = find(num[j].a);
			int bb = find(num[j].b);
			
			int aaa = find(num[j].a + n);
			int bbb = find(num[j].b + n);
			
			if((num[j].val >> i) & 1 ) // 不同为1 ,一个取0一个取1
			{
				if(aa == bb)
				{
					cout << -1 << endl;
					return 0;
				}
				if(aa == bbb) continue;
				
				merge(aa, bbb);
				merge(bb, aaa);
			}
			else // 相同为0, 都取1 或者都取0
			{
				if(aa == bbb )
				{
					cout << -1 << endl;
					return 0;
				}
				if(aa == bb) continue;
				
				merge(bb, aa);
				merge(bbb, aaa);
			}
		}
		for(int j = 1; j <= n; j ++) // 对于每个数字计算结果
		{
			res += (LL)min(sz[find(j)], sz[find(j+n)]) * (1 << i);
			sz[find(j)] = 0;
			sz[find(j+n)] = 0;
		}
	}
	
	cout << res << endl;
	return 0;
}
/*
3 3
1 2 1
2 3 1
1 3 1 

*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值