题目要求把点涂成白和黑两种颜色,如果一条边左右两端是不同的颜色的话,结果就异或这跳边的权值,求结果最大是多少
把边的贡献转换成点的贡献
我们只考虑白色点的情况下,如果一个点A是白色,就把结果异或上这一个点A周围的所有边,
如果在该点周围还有一个白色点B的话,那么我们同样把结果异或上这个点B的所有边
因为我们知道两个点是有线段相连,而且两个点都异或上该点周围的所有边了
所以两个点相邻的线段就被去掉了
其他点同理
这时候我们就可以把这个问题转换成一个线性基的问题
已知所以点的贡献是该点异或上周围所有边
求从n个点中选出一部分点染成白色的最大异或和
const int inf = 0x3f3f3f3f3f3f3f3f, N = 2e5 + 5, mod = 1e9 + 7;
vector<int>q[N];
int a[N];
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
q[i].clear(); a[i] = 0;
}
while (m--)
{
int u, v, w;
cin >> u >> v >> w;
q[u].push_back(w);
q[v].push_back(w);
}
for (int i = 1; i <= n; i++) {
for (auto w : q[i])
{
a[i] ^= w;
}
}
int k = 1;
for (int i = 32; i >= 0; i--)
{
for (int j = k; j <= n; j++) {
if (a[j] >> i & 1) {
swap(a[j], a[k]);
break;
}
}
if (!(a[k] >> i & 1)) continue;
for (int j = 1; j <= n; j++) {
if (j != k && (a[j] >> i & 1))
a[j] ^= a[k];
}
k++;
if (k == n + 1) break;
}
int res = 0;
for (int i = 1; i <= k; i++) {
res ^= a[i];
}
cout << res << "\n";
}
}