将每个数二进制表示下的每一位分开考虑,位与位之间不会互相影响,我们对有关系的两个点建图,建好后对每一位根据异或关系染色,(颜色的确定可以根据异或运算的自反性得到 即
A xor B xor B =A)如果染色出现矛盾,就可以确定该异或关系必然不能产生合法序列,直接输出-1即可,在染色种统1的个数,因为是异或操作,所以图中染色的0和1的位置可以互换,
所以我们再统计一个该联通块中点的总数,用总数减去1的个数就可以得到0的个数,其实这里的0和1表示的是图中两类相斥点的数量,你需要贪心的选择在数量较少的那一类填1,以使得序列的和最小。注意对于每一位都有可能出现多个不连通的联通分量,因为每个联通分量合法性相互之间不会影响,所以我们可以取每个联通分量的较小的那一类的数量然后累加。
这个是#define int long long 在超时的边缘
这个是手开long long
ACcode
#include <iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<cmath>
#include<queue>
#include<bitset>
#include<vector>
#include<map>
#include<unordered_map>
#define int long long
#define endl '\n'
#define lowbit(x) (x &-x)
#define mh(x) memset(x, -1, sizeof h)
#define debug(x) cerr << #x << "=" << x << endl;
#define brk exit(0);
using namespace std;
void inline TLE() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); }
const int N = 2e5 + 10;
const int M = 2 * N;
const int mod = 998244353;
const double esp = 1e-6;
const double pi = acos(-1);
typedef pair<int, int> PII;
typedef long long LL;
int e[2 * N], w[2 * N], ne[2 * N], h[N], cnt;
int color[31][N];
void add(int a, int b, int c) {
e[cnt] = b, w[cnt] = c, ne[cnt] = h[a], h[a] = cnt++;
}
int sum = 0;
int dfs(int u, int f, int itcolor)
{
sum++;
color[f][u] = itcolor;
//cout << itcolor << endl;
int res = itcolor;
for (int i = h[u];~i;i = ne[i]) {
int j = e[i];
if (color[f][j] == -1) {
res += dfs(j, f, ((w[i] >> f)&1) ^ itcolor);
}
else if (color[f][j] != ((w[i] >> f)&1) ^ itcolor) {
cout << "-1" << endl;
exit(0);
}
}
return res;
}
signed main()
{
TLE();
memset(color, -1, sizeof color);
memset(h, -1, sizeof h);
int n, m;
cin >> n >> m;
while (m--)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
add(b, a, c);
}
int p = 1;
int res = 0;
for (int i = 0;i < 31;i++)
{
for (int j = 1;j <= n;j++)
if (color[i][j] == -1)
{
sum = 0;
int t = dfs(j, i, 1);
res +=p* min(t, sum - t);
//cout <<sum<<" " <<t << endl;
}
p <<= 1LL;
}
cout << res << endl;
return 0;
}