Clarke and MST

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

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

Source
BestCoder Round #72 (div.2)


题目大意:求最大与生成树。


思路应该挺简单的,就是怎么简单的去实现。我们从每一位开始考虑:这一位有1的能否组成一颗生成树,因为我们是从最高位去看,所以若能组成,必然最优,否则继续往地位寻找。

若能组成,则把这一位二进制没有1的边全部删掉,也就是标记一下,以后不用即可。然后用这里面的边再去看下一位。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=3e5+10;
int T,n,m,f[N],res,vis[N],cnt;
struct node{
	int u,v,w;
}t[N];
vector<int> v[32];
int find(int x){
	return x==f[x]?x:f[x]=find(f[x]);
}
int mst(int k){
	for(int i=1;i<=n;i++)	f[i]=i;	int cnt=0;
	for(int i=0;i<v[k].size();i++){
		if(vis[v[k][i]])	continue;
		int fa=find(t[v[k][i]].u);	int fb=find(t[v[k][i]].v);
		if(fa!=fb)	cnt++,f[fa]=fb;
		if(cnt==n-1)	return 1;
	}
	return cnt==n-1;
}
signed main(){
	cin>>T;
	while(T--){
		scanf("%d %d",&n,&m); res=0;
		for(int i=1;i<=m;i++){
			scanf("%d %d %d",&t[i].u,&t[i].v,&t[i].w);
			for(int j=30;j>=0;j--)	if((t[i].w>>j)&1)	v[j].push_back(i);
		}
		for(int i=30;i>=0;i--){
			if(mst(i)){
				res|=(1<<i);
				for(int i=1;i<=m;i++)	if(t[i].w&(1<<i)==0)	vis[i]=1;
			}
		}
		printf("%d\n",res);
	}
	return 0;
}