Clarke and MST
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 266 Accepted Submission(s): 152
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.
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.
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
题意:给你一个图,有边权,构建一棵生成树,使得边权经过and(&)运算后结果最大,求这棵生成树最后的结果,不存在输出0
思路:用kruskul方法,排序时按照边权含有1的数量排序,优先添加1多的边,然后过程中计算就好了
ac代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stack>
#include<set>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define MAXN 1010000
#define LL long long
#define ll __int64
#define INF 0xfffffff
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
//head
struct s
{
int a,b;
int num;
int v;
}p[MAXN];
ll ans;
int pri[MAXN];
bool cmp(s aa,s bb)
{
return aa.num>bb.num;
}
int find(int x)
{
int r=x;
while(r!=pri[r])
r=pri[r];
int i=x,j;
while(i!=r)
{
j=pri[i];
pri[i]=r;
i=j;
}
return r;
}
void connect(int xx,int yy,int k)
{
int nx=find(xx);
int ny=find(yy);
if(nx!=ny)
{
pri[nx]=pri[ny];
ans=ans&k;
//printf("a=%d b=%d\n",xx,yy);
//printf("kkk:%I64d\n",ans);
}
}
int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
pri[i]=i;
for(i=0;i<m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int cnt=0;
int zz=z;
while(z)
{
z&=(z-1);
cnt++;
}
p[i].a=x;p[i].b=y;p[i].num=cnt;p[i].v=zz;
}
sort(p,p+m,cmp);
ans=p[0].num;
pri[p[0].a]=p[0].b;
for(i=1;i<m;i++)
{
//printf("...%d\n",p[i].num);
connect(p[i].a,p[i].b,p[i].v);
}
int ccnt=0;
for(i=1;i<=n;i++)
if(pri[i]==i)
ccnt++;
if(ccnt>1)
printf("0\n");
else
printf("%I64d\n",ans);
}
return 0;
}