HDU 5627 Clarke and MST &意义下最大生成树 贪心

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5627

题意:Bestcoder的一道题,让你求&意义下的最大生成树。

解法:

贪心,我们从高位到低位贪心,如果含有这一位的边能够构成一棵树的话,我们就可以直接把其他不含有这一位的边全部去掉

然后重复这个行为

这个贪心显然正确啦,至于判断能否构成一颗树,就用并查集就好啦

 

//HDU 5627

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+6;
int x[maxn], y[maxn], w[maxn], flag[maxn], fa[maxn];
int find_set(int x){if(x == fa[x]) return x; return fa[x] = find_set(fa[x]);}
void union_set(int x, int y){x = find_set(x), y = find_set(y); if(x!=y) fa[x] = y;}
int n, m;

int main(){
    int T; scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++) scanf("%d%d%d", &x[i], &y[i], &w[i]);
        int ans = 0;
        for(int i = 30; i >= 0; i--){
            for(int j = 1; j <= n; j++) fa[j] = j;
            for(int j = 1; j <= m; j++){
                if((w[j]&ans) == ans && (w[j]>>i&1)) flag[j] = 1;
                else flag[j] = 0;
            }
            for(int j = 1; j <= m; j++){
                if(flag[j]){
                    union_set(x[j], y[j]);
                }
            }
            bool ok = 1;
            int p = find_set(1);
            for(int j = 2; j <= n; j++){
                if(find_set(j) != p){
                    ok = 0;
                }
            }
            if(ok) ans |= (1<<i);
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

posted @ 2017-03-21 15:50  zxycoder  阅读(296)  评论(0编辑  收藏  举报