hoj12616 Median Tree ——最小生成树入门题&&比赛残留题_Kruscal算法

题目链接: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()函数……以后得注意了。

  可是比赛的时候,这货我都没学过……所以再简单也还是不会……所以,以后学东西得加快速度,至少知识点都知道,简单题得会做。

posted on 2013-05-01 21:43  aries__liu  阅读(202)  评论(0编辑  收藏  举报