hdoj Clarke and MST 5627(求位运算and后得到的最大生成树)(并查集&位运算)好题

来源:互联网 发布:窄斑凤尾蛱蝶 标本淘宝 编辑:程序博客网 时间:2024/05/16 18:34

Clarke and MST

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


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 n1 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 n1 edges. 
Now he wants to figure out the maximum spanning tree.
 

Input
The first line contains an integer T(1T5), the number of test cases. 
For each test case, the first line contains two integers n,m(2n300000,1m300000), denoting the number of points and the number of edge respectively. 
Then m lines followed, each line contains three integers x,y,w(1x,yn,0w109), 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
14 51 2 51 3 31 4 22 3 13 4 7
 

Sample Output
1
问题描述
克拉克是一名人格分裂患者。某一天克拉克变成了一名图论研究者。  他学习了最小生成树的几个算法,于是突发奇想,想做一个位运算and的最大生成树。  一棵生成树是由n-1n1条边组成的,且nn个点两两可达。一棵生成树的大小等于所有在生成树上的边的权值经过位运算and后得到的数。  现在他想找出最大的生成树。
输入描述
第一行是一个整数T(1 \le T \le 5)T(1T5),表示数据组数。  每组数据第一行是两个整数n, m(1 \le n, m \le 300000)n,m(1n,m300000),分别表示点个数和边个数。其中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(1x,yn,0w109),表示x, yx,y之间有一条大小为ww的边。
输出描述
每组数据输出一行一个数,表示答案。若不存在生成树,输出00
输入样例
14 51 2 51 3 31 4 22 3 13 4 7
输出样例
1
#include<stdio.h>#include<string.h>#include<algorithm>#define ING 0x3f3f3f3f#define ll long long#define N 300010using namespace std;struct zz{int u;int v;int w;}p[N];int f[N];int n,m;int find(int x){return x==f[x]?x:f[x]=find(f[x]);}int judge(int x){int i,j;for(i=1;i<=n;i++)f[i]=i;for(i=0;i<m;i++) {if((p[i].w&x)==x)//如果加入第i条边后不影响结果,则将这条边加入这棵树 {int fx=find(p[i].u);int fy=find(p[i].v);if(fx!=fy)f[fx]=fy;}}int cnt=0,k=find(1);for(i=2;i<=n;i++)//判断加入进去的边是否组成一颗树。 if(find(i)!=k)return 0;return 1;}int main(){int t,i,j;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(i=0;i<m;i++)scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w);int ans=0;for(i=31;i>=0;i--)//枚举所有答案 {int tmp=ans|(1<<i);if(judge(tmp))ans=tmp;}printf("%d\n",ans);}return 0;}

0 0