克拉克是一名人格分裂患者。某一天克拉克变成了一名图论研究者。
他学习了最小生成树的几个算法,于是突发奇想,想做一个位运算and的最大生成树。
一棵生成树是由n-1n−1条边组成的,且nn个点两两可达。一棵生成树的大小等于所有在生成树上的边的权值经过位运算and后得到的数。
现在他想找出最大的生成树。
输入描述
第一行是一个整数T(1 \le T \le 5)T(1≤T≤5),表示数据组数。
每组数据第一行是两个整数n, m(1 \le n, m \le 300000)n,m(1≤n,m≤300000),分别表示点个数和边个数。其中n, m > 100000n,m>100000的数据最多一组。
接下来mm行,每行33个整数x, y, w(1 \le x, y \le n, 0 \le w \le 10^9)x,y,w(1≤x,y≤n,0≤w≤10
9
),表示x, yx,y之间有一条大小为ww的边。
输出描述
每组数据输出一行一个数,表示答案。若不存在生成树,输出00。
输入样例
1
4 5
1 2 5
1 3 3
1 4 2
2 3 1
3 4 7
输出样例
1
最大生成树,只不过答案是用&计算。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y,c;
} std1[300006];
int f[300006];
bool cmp(node n,node m)
{
return n.c>m.c;
}
int find(int r)
{
if(r==f[r])
{
return r;
}
else
{
f[r]=find(f[r]);
return f[r];
}
}
int merge(node n)
{
int xx=find(n.x);
int yy=find(n.y);
if(xx!=yy)
{
f[yy]=xx;
return 1;
}
return 0;
}
int main()
{
int t,n,m,j,k,i;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
for(i=1; i<=n; i++)
{
f[i]=i;
}
for(i=1; i<=m; i++)
{
scanf("%d %d %d",&std1[i].x,&std1[i].y,&std1[i].c);
}
sort(std1+1,std1+m+1,cmp);
int f=0;
int cont=0;
int sum;
int k=1;
for(i=1; i<=m; i++)
{
if(merge(std1[i])==1)
{
if(k==1)
{
k=0;
merge(std1[i]);
sum=std1[i].c;
}
else if(k==0)
{
sum&=std1[i].c;
merge(std1[i]);
}
cont++;
}
if(cont==n-1)
{
f=1;
}
}
if(f==0)
{
printf("0\n");
}
else
{
printf("%d\n",sum);
}
}
return 0;
}