HDU

题目链接
题目大意:让你求一棵生成树,使这棵生成树所有的边通过与运算得到的值最大。
  假设通过与运算得到的最大值为m,那么m每个二进制位上的1都应该与这棵树所有边的权值的二进制位对应位置的1相同。又因为进位制的性质,高位的数比所有低位的数之和还要大。所以我们可以通过从高到低来枚举二进制位,如果这个位上为1的边可以构成一棵生成树,那么就让这位为0的边都删掉,继续枚举下一位。
  关于删边,链表是一个好方法,还有一个方法是通过一个数组来标记边,被标记的边就是被删掉的边。

//https://www.cnblogs.com/shuitiangong/
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '
'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==================================================
")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  1000000009;
const int INF = 0x3f3f3f3f;
const int maxn = 3e5+10;
struct Edge {
    int u, v; ll w;
    bool operator < (const Edge &a) const {
        return w > a.w;
    }
} edge[maxn];
int n, m, p[maxn]; ll ans; bool del[maxn];
int find(int root) {
    int son = root, tmp;
    while(root != p[root]) root = p[root];
    while(son != root) {
        tmp = p[son];
        p[son] = root;
        son = tmp;
    }
    return root;
}
void kruskal(ll num) {
    int s = 0;
    for (int i = 0; i<=n; ++i) p[i] = i;
    for (int i = 0; i<m; ++i)
        if (!del[i] && (edge[i].w & num) && find(p[edge[i].u]) != find(p[edge[i].v])) {
            ++s;
            p[find(edge[i].u)] = find(edge[i].v);
        }
    if (s == n-1) {
        for (int i = 0; i<m; ++i)
            if (~edge[i].w&num) del[i] = true;
        ans |= num;
    }
}
int main(void) {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i<m; ++i)
            scanf("%d%d%lld", &edge[i].u, &edge[i].v, &edge[i].w);
        sort(edge, edge+m);
        ans = 0;
        for (ll i = 32; i>=0; --i) {
            ll tmp = 1LL << i;
            kruskal(tmp);
        }
        printf("%lld
", ans);
        memset(del, 0, sizeof(del[0])*(n+5));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/12619184.html