HDU 5627 (生成树)
2016-02-15 21:47
316 查看
Clarke and MST
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 282 Accepted Submission(s): 157
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的那些边能不能组成一棵ST,如果可以就更新边集,复杂度O(32*n)。
#include <iostream> #include <cmath> #include <cstdlib> #include <time.h> #include <vector> #include <cstdio> #include <cstring> using namespace std; #define maxn 311111 #define maxm 611111 struct node { int u, v; long long w; }; vector <node> edge[2]; int n, m; int fa[maxn]; int find (int x) { return fa[x] == x ? fa[x] : fa[x] = find (fa[x]); } bool ok (int id) { //判断能不能构成一个联通分量 for (int i = 1; i <= n; i++) fa[i] = i; int Max = edge[id].size (); for (int i = 0; i < Max; i++) { int u = edge[id][i].u, v = edge[id][i].v; int p1 = find (u), p2 = find (v); if (p1 != p2) fa[p1] = p2 ; } int gg = find (1); for (int i = 2; i <= n; i++) { if (find (i) != gg) return 0; } return 1; } bool is_1 (long long num, int id) { //判断num的id位是不是1 id--; num >>= id; return (num&1); } bool work (int id) { //判断id位能否为1 int Max = edge[0].size (); for (int i = 0; i < Max; i++) { if (is_1 (edge[0][i].w, id)) { edge[1].push_back (edge[0][i]); } } if (ok (1)) { edge[0].clear (); int Max = edge[1].size (); for (int i = 0; i < Max; i++) { edge[0].push_back (edge[1][i]); } return 1; } return 0; } int main () { int t; scanf ("%d", &t); while (t--) { scanf ("%d%d", &n, &m); edge[0].clear (); edge[1].clear (); for (int i = 1; i <= m; i++) { int u, v; long long w; scanf ("%d%d%lld", &u, &v, &w); edge[0].push_back ((node){u, v, w}); } if (!ok (0)) { printf ("0\n"); continue; } long long ans = 0; for (int i = 32; i >= 1; i--) { edge[1].clear (); if (work (i)) { ans <<= 1; ans++; } else ans <<= 1; } printf ("%lld\n", ans); } return 0; }
相关文章推荐
- javascript面向对象编程方式
- 面向对象编程风格 & 基于对象编程(boost::bind/function)
- javascript正则表达式验证IP,URL
- VC的常用调试方法
- 第35课:Spark系统运行内幕机制循环流程
- strtok是个坏东西
- Gym 100712A - Who Is The Winner
- C#面向对象基础
- HighGUI 图形用户界面
- 无向图最小生成树(prim算法)
- leetcode(207) Course Schedule即拓扑排序讲解
- 【POJ 1451】T9 中文题意&题解&代码(c++)
- HTML静态网页--表单验证和事件
- HTML静态网页--JavaScript-Window.document对象
- Leetcode1:Two Sum
- Android杂谈之Android数据存储方式
- VC的常用调试方法
- HTML静态网页--JavaScript-DOW操作
- HTML静态网页--JavaScript-语法
- 初探12306售票算法