hdu5627 Clarke and MST (并查集)

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 311    Accepted Submission(s): 173


Problem Description
Clarke is a patient with multiple personality disorder. One day he turned into a learner of graph theory. 
He learned some algorithms of minimum spanning tree. Then he had a good idea, he wanted to find the maximum spanning tree with bit operation AND. 
A spanning tree is composed by n−1 edges. Each two points of n points can reach each other. The size of a spanning tree is generated by bit operation AND with values of n−1 edges. 
Now he wants to figure out the maximum spanning tree.
 

Input
The first line contains an integer T(1≤T≤5), the number of test cases. 
For each test case, the first line contains two integers n,m(2≤n≤300000,1≤m≤300000), denoting the number of points and the number of edge respectively. 
Then m lines followed, each line contains three integers x,y,w(1≤x,y≤n,0≤w≤109), denoting an edge between x,y with value w. 
The number of test case with n,m>100000 will not exceed 1. 
 

Output
For each test case, print a line contained an integer represented the answer. If there is no any spanning tree, print 0.
 

Sample Input
1 4 5 1 2 5 1 3 3 1 4 2 2 3 1 3 4 7
 

Sample Output
1
 
题意:给你n个点m条边以及m条边的权值,让你构造一棵生成树,使得生成树的权值and和最大。
思路:我们可以贪心地枚举二进制中的每一位,从30到0,然后判断有该位的值为1的所有权值中能不能形成一棵生成树,如果有,那么这些权值的边为可选边,看能不能组成下一位。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 300050
struct node{
    int x,y,w;
}e[maxn];
int ok[maxn],pre[maxn],ran[maxn];
void makeset(int x){
    pre[x]=x;
    ran[x]=0;
}
int findset(int x){
    int i,j=x,r=x;
    while(r!=pre[r])r=pre[r];
    while(j!=pre[j]){
        i=pre[j];
        pre[j]=r;
        j=i;
    }
    return r;

}

int main()
{
    int n,m,i,j,T,t;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
        }
        for(i=1;i<=m;i++)ok[i]=1;
        int sum=0;
        for(t=30;t>=0;t--){
            for(i=1;i<=n;i++){
                makeset(i);
            }
            int ans=n;
            for(i=1;i<=m;i++){
                if(ok[i] && (e[i].w&(1<<t) ) ){
                    int x=findset(e[i].x);
                    int y=findset(e[i].y);
                    if(x==y)continue;
                    ans--;
                    if(ran[x]>ran[y]){
                        pre[y]=x;
                    }
                    else{
                        pre[x]=y;
                        if(ran[x]==ran[y])ran[y]++;
                    }


                }


            }
            if(ans==1){
                sum|=(1<<t);
                for(i=1;i<=m;i++){
                    if(ok[i] && (e[i].w&(1<<t) )){
                        ok[i]=1;
                    }
                    else ok[i]=0;
                }


            }



        }
        printf("%d\n",sum);




    }
    return 0;




}


posted @ 2016-02-16 14:46  Herumw  阅读(249)  评论(0)    收藏  举报