hoj12616 Median Tree ——最小生成树入门题&&比赛残留题_Kruscal算法
2013-05-01 21:43
267 查看
题目链接: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的那一条边即可退出。
然后又修改了一下,根据严格的中位数的定义。在kruscal的过程中,计算出中间的两个数字的和,然后取平均值,输出。也过了……
这货也不难。关键是,自己每次写kruscal的时候,总是忘了写init()函数……以后得注意了。
可是比赛的时候,这货我都没学过……所以再简单也还是不会……所以,以后学东西得加快速度,至少知识点都知道,简单题得会做。
题目大意:
给n个点,m条边,求一棵生成树,使得这个生成树的边的权值的中位数最小。输出这个中位数。
题目思路:
和poj1861&&zoj1542的思路是一样的。可以证明要求的树就是最小生成树。然后就是中位数的概念:长度为N的数列的中位数,就是(N+1)/2位置的数字。百度百科里面貌似不是严格的中位数的概念。
开始写了一遍按照那种不严格的中位数的定义写的。过了。kruscal的过程中,只需要计算到(n-1+1)/2-1的那一条边即可退出。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <cmath> #include <algorithm> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; typedef long long int LL; const int MAXN = 0x3f3f3f3f; const int MIN = -0x3f3f3f3f; const double eps = 1e-9; const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, {1,1},{1,-1},{-1,-1}}; int n, m; const int em = 10000+10, vm = 1000+10; typedef struct Edge { int u, v, w; bool operator < (const Edge &other) const { return w < other.w; } }Edge; Edge edge[em]; int parent[vm]; void init() { for (int i = 1; i <= n; ++i) parent[i] = -1; } int Find(int x) { int s; for (s = x; parent[s] >= 0; s = parent[s]) ; while (s != x) { int tmp = parent[x]; parent[x] = s; x = tmp; } return s; } void Union(int R1, int R2) { int r1 = Find(R1), r2 = Find(R2), tmp = parent[r1] + parent[r2]; if (parent[r1] > parent[r2]) { parent[r1] = r2; parent[r2] = tmp; } else { parent[r2] = r1; parent[r1] = tmp; } } void kruscal() { init(); int i, j, res, u, v, w, cnt = 0; for (i = 0; i < m; ++i) { u = edge[i].u; v = edge[i].v; w = edge[i].w; if (Find(u) != Find(v)) { res = w; Union(u, v); if (cnt == (n)/2 - 1) { printf("%d\n", res); break; } cnt++; } } } int main(void){ #ifndef ONLINE_JUDGE freopen("hoj12616.in", "r", stdin); #endif int i, j; while (~scanf("%d%d", &n, &m) && (m||n)) { for (i = 0; i < m; ++i) { scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); } sort(edge, edge + m); kruscal(); } return 0; }
然后又修改了一下,根据严格的中位数的定义。在kruscal的过程中,计算出中间的两个数字的和,然后取平均值,输出。也过了……
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <cmath> #include <algorithm> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; typedef long long int LL; const int MAXN = 0x3f3f3f3f; const int MIN = -0x3f3f3f3f; const double eps = 1e-9; const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, {1,1},{1,-1},{-1,-1}}; int n, m; const int em = 10000+10, vm = 1000+10; typedef struct Edge { int u, v, w; bool operator < (const Edge &other) const { return w < other.w; } }Edge; Edge edge[em]; int parent[vm]; void init() { for (int i = 1; i <= n; ++i) parent[i] = -1; } int Find(int x) { int s; for (s = x; parent[s] >= 0; s = parent[s]) ; while (s != x) { int tmp = parent[x]; parent[x] = s; x = tmp; } return s; } void Union(int R1, int R2) { int r1 = Find(R1), r2 = Find(R2), tmp = parent[r1] + parent[r2]; if (parent[r1] > parent[r2]) { parent[r1] = r2; parent[r2] = tmp; } else { parent[r2] = r1; parent[r1] = tmp; } } void kruscal() { init(); int i, j, res, u, v, w, cnt = 0, od; bool flag = false; for (i = 0; i < m; ++i) { u = edge[i].u; v = edge[i].v; w = edge[i].w; if (Find(u) != Find(v)) { res = w; Union(u, v); if (((n-1)&1==0) && (cnt ==(n-1)/2)) { od = w; } else if ( ((n-1)&1==0) && (cnt==(n-1)/2+1) ) { printf("%d\n", (od + res) / 2 ); break; } else if (((n-1)&1)&& (cnt==(n)/2-1)) { printf("%d\n", res); break; } cnt++; } } } int main(void){ #ifndef ONLINE_JUDGE freopen("hoj12616.in", "r", stdin); #endif int i, j; while (~scanf("%d%d", &n, &m) && (m||n)) { for (i = 0; i < m; ++i) { scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); } sort(edge, edge + m); kruscal(); } return 0; }
这货也不难。关键是,自己每次写kruscal的时候,总是忘了写init()函数……以后得注意了。
可是比赛的时候,这货我都没学过……所以再简单也还是不会……所以,以后学东西得加快速度,至少知识点都知道,简单题得会做。
相关文章推荐
- poj1861&&zoj1542 Network ——最小生成树入门题_Kruscal算法
- hiho刷题日记——第二十七天最小生成树二·Kruscal算法
- 最小生成树算法---Kruscal算法和Prim算法(入门)
- hiho一下 第二十七周:最小生成树二·Kruscal算法
- #1098 : 最小生成树二·Kruscal算法
- (kruscal12.1.1)POJ 2421 Constructing Roads(使用kruscal算法来生成最小生成树&&计算最小带权路径和)
- poj 最小生成树入门水题 1251 && 1258 && 1287 && 2395 && 2485 && 2377
- poj 最小生成树入门水题 1251 && 1258 && 1287 && 2395 && 2485 && 2377
- poj2048&&zoj1751 Highways ——最小生成树入门题_Prim算法
- hihoCoder 1098 : 最小生成树二·Kruscal算法
- hihoCoder - hiho一下 第二十七周 - A - 最小生成树二·Kruscal算法
- #1098 : 最小生成树二·Kruscal算法
- poj2421 Constructing Roads ——最小生成树入门题_Kruscal算法
- zoj1203 Swordfish ——最小生成树入门题_Kruscal算法
- hihocoder1098最小生成树(kruscal算法)
- poj2395--Out of Hay(最小生成树)
- 算法篇-7-贪心算法-Huffman编码&Dijkstra单源最短路径&Kruskal最小生成树
- hdu 1233 最小生成树 "还是畅通工程"
- zoj1586 QS Network ——最小生成树入门题_Prim算法
- hiho一下 第二十六周---最小生成树一·Prim算法