# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
1143644 | Rufat | Friend (IOI14_friend) | C++20 | 0 ms | 0 KiB |
// Global variable to store the best total so far.
int best;
// dp: from a given bitmask of vertices still “active” we record an upper bound.
unordered_map<uint64_t,int> memo;
// rec( mask, cur ) = try to complete an independent set starting from
// the set 'mask' (of vertices still available) having already total weight 'cur'
void rec(uint64_t mask, int cur, const vector<int>& weight,
const vector<uint64_t>& nbr) {
if(mask==0) {
best = max(best, cur);
return;
}
// Use memoization to prune
if(memo.count(mask) && memo[mask] + cur <= best) return;
// Choose a vertex v from mask (say, the least–significant one)
int v = __builtin_ctzll(mask);
// Option 1: take vertex v.
uint64_t mask2 = mask & ~(1ULL << v) & ~nbr[v]; // remove v and its neighbours
rec(mask2, cur + weight[v], weight, nbr);
// Option 2: do not take vertex v.
rec(mask & ~(1ULL << v), cur, weight, nbr);
memo[mask] = best - cur; // record an upper bound for mask
}
// The function to be implemented.
int findSample(int n, int confidence[], int host[], int protocol[]) {
// Build the graph.
// For each vertex we will compute a bitmask of its neighbours.
// We assume n is small enough (say n<=64) so that we can use a 64–bit integer.
vector<uint64_t> nbr(n, 0ULL);
// At stage 0, person 0 is in the network.
// We also keep, for each vertex, the set of its current friends.
vector< set<int> > friends(n);
// Note: confidence[i] is the weight of vertex i.
vector<int> weight(n);
for (int i = 0; i < n; i++)
weight[i] = confidence[i];
// Process stages 1 .. n–1:
for (int i = 1; i < n; i++) {
int h = host[i]; // host of stage i
int p = protocol[i]; // protocol code: 0, 1, or 2
if(p == 0) {
// IAmYourFriend: add edge (i, h)
friends[i].insert(h);
friends[h].insert(i);
} else if(p == 1) {
// MyFriendsAreYourFriends: add, for every friend f of h, edge (i, f)
for (int f : friends[h]) {
friends[i].insert(f);
friends[f].insert(i);
}
} else if(p == 2) {
// WeAreYourFriends: add edge (i, h) and for every friend f of h, edge (i, f)
friends[i].insert(h);
friends[h].insert(i);
for (int f : friends[h]) {
friends[i].insert(f);
friends[f].insert(i);
}
}
// (Optionally, you could also update a "host–tree" structure but here we only need the graph.)
}
// Now fill in the neighbour bitmasks.
for (int i = 0; i < n; i++){
for (int j : friends[i]) {
// (We assume that 0 <= j < n.)
nbr[i] |= (1ULL << j);
}
}
// Now solve the maximum–weight independent set by recursion.
best = 0;
memo.clear();
// Initially all vertices are available: mask = (1<<n)-1.
uint64_t all = (n==64 ? ~0ULL : ((1ULL << n) - 1));
rec(all, 0, weight, nbr);
return best;
}