Clarke and MST
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 196 Accepted Submission(s): 100
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
题目大意:
最大生成树。挑选最大按位&的路线。
思路:用二进制的方法一个一个的判断最高位即可。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<stack> #include<map> using namespace std; typedef long long ll; int n, m; struct edge{ ll from, to; ll cost; }ed[300000 + 50]; int par[300000 + 50], level[300000 + 50]; int cnt; void init(){ for (int i = 0; i < n; i++){ par[i] = i; level[i] = 0; } } int find(int x){ if (par[x] == x) return x; return par[x] = find(par[x]); } bool same(int x, int y){ return find(x) == find(y); } void unite(int x, int y){ x = find(x); y = find(y); if (x == y) return ; if (level[x] > level[y]){ par[y] = x; } else { par[x] = y; if (level[x] == level[y]) level[x]++; } } void kruskal(){ ll res = 0; for (int i = 30; i >= 0; i--){ res += (1 << i); init(); cnt = 0; for (int j = 0; j < m; j++){ edge e = ed[j]; if ((e.cost & res) == res){ if (!same(e.from, e.to)){ unite(e.from, e.to); cnt++; } } } if (cnt != n - 1) res -= (1 << i); } printf("%d\n", res); } int main(){ int t; scanf("%d", &t); while (t--){ scanf("%d%d", &n, &m); for (int i = 0; i < m; i++){ scanf("%I64d%I64d%I64d", &ed[i].from, &ed[i].to, &ed[i].cost); } kruskal(); } return 0; } </map></stack></queue></cmath></cstring></algorithm></cstdio>