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
题意:给你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;
}