题目大意:
给你一堆牌,牌有红蓝面,每面上有个数字,每次取两张,获得一个值,可以说A的红面与B的蓝面的异或,也可以是A蓝^B红。 最后会剩下一堆牌,求如何让取到的值最小。
。。其实题目看懂了就是道裸题=======
两个点的边权为 min(a.r^b.b,a.b^b.r)
然后跑mst吧。。。。
(PS:刷钱的话记得有small large两个版本)
#include <bits/stdc++.h>
using namespace std;
struct edge{
int from, to, v;
bool operator< (const edge& rhs) const {
return v < rhs.v;
}
};
int r[100], b[100], p[100];
vector<edge> graph;
int findp(int x){
return x == p[x] ? x : p[x] = findp(p[x]);
}
int main(){
int t;
cin >> t;
for(int tt = 1; tt <= t; tt++){
int n;
cin >> n;
for(int i = 0; i < n; i++) cin >> r[i];
for(int i = 0; i < n; i++) cin >> b[i];
graph.clear();
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
int x = r[i] ^ b[j], y = r[j] ^ b[i];
graph.push_back({i, j, min(x, y)});
}
}
sort(graph.begin(), graph.end());
for(int i = 0; i < n; i++) p[i] = i;
long long ans = 0;
for(edge &e : graph){
int pa = findp(e.from), pb = findp(e.to);
if(pa != pb){
ans += e.v; p[pb] = pa;
}
}
printf("Case #%d: %lld\n", tt, ans);
}
return 0;
}