题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12616
题目大意:
给n个点,m条边,求一棵生成树,使得这个生成树的边的权值的中位数最小。输出这个中位数。
题目思路:
和poj1861&&zoj1542的思路是一样的。可以证明要求的树就是最小生成树。然后就是中位数的概念:长度为N的数列的中位数,就是(N+1)/2位置的数字。百度百科里面貌似不是严格的中位数的概念。
开始写了一遍按照那种不严格的中位数的定义写的。过了。kruscal的过程中,只需要计算到(n-1+1)/2-1的那一条边即可退出。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <cmath> 12 #include <algorithm> 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 using namespace std; 16 typedef long long int LL; 17 const int MAXN = 0x3f3f3f3f; 18 const int MIN = -0x3f3f3f3f; 19 const double eps = 1e-9; 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 21 {1,1},{1,-1},{-1,-1}}; 22 int n, m; 23 const int em = 10000+10, vm = 1000+10; 24 typedef struct Edge { 25 int u, v, w; 26 bool operator < (const Edge &other) const { 27 return w < other.w; 28 } 29 }Edge; 30 Edge edge[em]; 31 int parent[vm]; 32 void init() 33 { 34 for (int i = 1; i <= n; ++i) parent[i] = -1; 35 } 36 int Find(int x) 37 { 38 int s; 39 for (s = x; parent[s] >= 0; s = parent[s]) ; 40 while (s != x) { 41 int tmp = parent[x]; parent[x] = s; x = tmp; 42 } 43 return s; 44 } 45 void Union(int R1, int R2) 46 { 47 int r1 = Find(R1), r2 = Find(R2), tmp = parent[r1] + parent[r2]; 48 if (parent[r1] > parent[r2]) { 49 parent[r1] = r2; parent[r2] = tmp; 50 } else { 51 parent[r2] = r1; parent[r1] = tmp; 52 } 53 } 54 void kruscal() 55 { 56 init(); 57 int i, j, res, u, v, w, cnt = 0; 58 for (i = 0; i < m; ++i) { 59 u = edge[i].u; v = edge[i].v; w = edge[i].w; 60 if (Find(u) != Find(v)) { 61 res = w; Union(u, v); 62 if (cnt == (n)/2 - 1) { 63 printf("%d\n", res); break; 64 } 65 cnt++; 66 } 67 } 68 } 69 70 int main(void){ 71 #ifndef ONLINE_JUDGE 72 freopen("hoj12616.in", "r", stdin); 73 #endif 74 int i, j; 75 while (~scanf("%d%d", &n, &m) && (m||n)) { 76 for (i = 0; i < m; ++i) { 77 scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); 78 } 79 sort(edge, edge + m); 80 kruscal(); 81 } 82 83 return 0; 84 }
然后又修改了一下,根据严格的中位数的定义。在kruscal的过程中,计算出中间的两个数字的和,然后取平均值,输出。也过了……
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <cmath> 12 #include <algorithm> 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 using namespace std; 16 typedef long long int LL; 17 const int MAXN = 0x3f3f3f3f; 18 const int MIN = -0x3f3f3f3f; 19 const double eps = 1e-9; 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 21 {1,1},{1,-1},{-1,-1}}; 22 int n, m; 23 const int em = 10000+10, vm = 1000+10; 24 typedef struct Edge { 25 int u, v, w; 26 bool operator < (const Edge &other) const { 27 return w < other.w; 28 } 29 }Edge; 30 Edge edge[em]; 31 int parent[vm]; 32 void init() 33 { 34 for (int i = 1; i <= n; ++i) parent[i] = -1; 35 } 36 int Find(int x) 37 { 38 int s; 39 for (s = x; parent[s] >= 0; s = parent[s]) ; 40 while (s != x) { 41 int tmp = parent[x]; parent[x] = s; x = tmp; 42 } 43 return s; 44 } 45 void Union(int R1, int R2) 46 { 47 int r1 = Find(R1), r2 = Find(R2), tmp = parent[r1] + parent[r2]; 48 if (parent[r1] > parent[r2]) { 49 parent[r1] = r2; parent[r2] = tmp; 50 } else { 51 parent[r2] = r1; parent[r1] = tmp; 52 } 53 } 54 void kruscal() 55 { 56 init(); 57 int i, j, res, u, v, w, cnt = 0, od; 58 bool flag = false; 59 for (i = 0; i < m; ++i) { 60 u = edge[i].u; v = edge[i].v; w = edge[i].w; 61 if (Find(u) != Find(v)) { 62 res = w; Union(u, v); 63 if (((n-1)&1==0) && (cnt ==(n-1)/2)) { 64 od = w; 65 } 66 else if ( ((n-1)&1==0) && (cnt==(n-1)/2+1) ) { 67 printf("%d\n", (od + res) / 2 ); break; 68 } 69 else if (((n-1)&1)&& (cnt==(n)/2-1)) { 70 printf("%d\n", res); break; 71 } 72 cnt++; 73 } 74 } 75 } 76 77 int main(void){ 78 #ifndef ONLINE_JUDGE 79 freopen("hoj12616.in", "r", stdin); 80 #endif 81 int i, j; 82 while (~scanf("%d%d", &n, &m) && (m||n)) { 83 for (i = 0; i < m; ++i) { 84 scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); 85 } 86 sort(edge, edge + m); 87 kruscal(); 88 } 89 90 return 0; 91 }
这货也不难。关键是,自己每次写kruscal的时候,总是忘了写init()函数……以后得注意了。
可是比赛的时候,这货我都没学过……所以再简单也还是不会……所以,以后学东西得加快速度,至少知识点都知道,简单题得会做。