HDOJ 1233 还是畅通工程(并查集、kruscal算法 + prim)
2014-04-19 21:33
393 查看
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1233
这是我第一次接触到算法~~想想还有点小激动诶~
这个题就是一个简单的最小生成树。
会想到去写这道题是因为我写了1232,那是一个简单的并查集的题目。水过1232之后,就顺便看了看1233。结果,这题纠结了我好久啊!!抓狂!!后面龙酱帮我捉虫的时候才发现竟然是并查集写错了。。重写一遍1232去QAQ
其实是因为不理解并查集啦。。当时死记硬背,只是把并查集的框架背了下来,结果背错了ORZ..
1233题因为是用的kruskal,所以会用到并查集。最小生成树还可以用prime算法做,但是我还没看0.0
so,what is bingchaji?(请首先阅读并查集的百度百科或者维基百科)
首先并查集有个father数组存储每个元素的元祖。father数组的下标代表元素,里头则存储着他们的老爸(当然老爸和自己是一个元祖)或者元祖,比如元素i的祖先是j,则表示为father[i] = j;如果该元素就是元祖,则存储自己,如father[j] = j。
然后还有一个find函数,用来寻找元祖的。
似乎还可以路径压缩,下次琢磨一下。
kruskal算法就是先把边存起来,然后按边权排序,再利用并查集查询是否同一元祖(或者两个朋友or亲戚有没有关系、能不能从别的路径走通两个村庄)按照顺序来一个个挑选是否构建这条边。如果同意元祖,不构建;若非同一元祖,构建。
因为已经按边权排序,所以构建边的时候边权是递增的,当所有元素都连接时,总边权应为最小(因为是贪心,所以如果有那种比较厉害的数据可能过不了)。
下面是ac代码:
补上prim的解法:
这是我第一次接触到算法~~想想还有点小激动诶~
这个题就是一个简单的最小生成树。
会想到去写这道题是因为我写了1232,那是一个简单的并查集的题目。水过1232之后,就顺便看了看1233。结果,这题纠结了我好久啊!!抓狂!!后面龙酱帮我捉虫的时候才发现竟然是并查集写错了。。重写一遍1232去QAQ
其实是因为不理解并查集啦。。当时死记硬背,只是把并查集的框架背了下来,结果背错了ORZ..
1233题因为是用的kruskal,所以会用到并查集。最小生成树还可以用prime算法做,但是我还没看0.0
so,what is bingchaji?(请首先阅读并查集的百度百科或者维基百科)
首先并查集有个father数组存储每个元素的元祖。father数组的下标代表元素,里头则存储着他们的老爸(当然老爸和自己是一个元祖)或者元祖,比如元素i的祖先是j,则表示为father[i] = j;如果该元素就是元祖,则存储自己,如father[j] = j。
然后还有一个find函数,用来寻找元祖的。
int find(int i) { if (i == father[i]) return i; //找到元祖 else return father[i] = find(father[i]); //存储数与下标不相等,还没有找到元祖~~~ }
似乎还可以路径压缩,下次琢磨一下。
kruskal算法就是先把边存起来,然后按边权排序,再利用并查集查询是否同一元祖(或者两个朋友or亲戚有没有关系、能不能从别的路径走通两个村庄)按照顺序来一个个挑选是否构建这条边。如果同意元祖,不构建;若非同一元祖,构建。
因为已经按边权排序,所以构建边的时候边权是递增的,当所有元素都连接时,总边权应为最小(因为是贪心,所以如果有那种比较厉害的数据可能过不了)。
下面是ac代码:
#include<stdio.h> #include<stdlib.h> int father[100]; //用结构体来做方便排序 struct node { int u; //村庄一号 int v; //村庄二号 int dis; //公路长,即边权 }x[5000]; int find(int i) { if (i == father[i]) return i; //找到元祖 else return father[i] = find(father[i]); //存储数与下标不相等,还没有找到元祖 } int cmp(const void *a, const void *b) //qsort的比较函数,这个表示从小到大排。 { return (*(node *)a).dis > (*(node *)b).dis ? 1 : -1; //下次要排别的变量,只要改掉node和.dis就可以了。至于为什么是1和-1的返回值,不知道,背的..T^T } int main() { int N; x[0].dis = 0; //防止这个不用的dis因为没初始化结果在排序的时候乱入 //freopen("1233.txt", "r", stdin); while(scanf("%d", &N) != EOF && N) { int i; int road; //总共可修的公路条数 int sum = 0; //总边权 int m = 0; //实际修路数,计数用 road = N * (N-1) / 2; sum = 0; for (i = 1; i <= N; i++) father[i] = i; //初始化father数组 for (i = 1; i <= road; i++) scanf("%d%d%d", &x[i].u, &x[i].v, &x[i].dis); //储存边 qsort(x+1, road, sizeof(x[0]), cmp); //按边权排序 for (i = 1; i <= road ;i++) { int s1 = find(x[i].u); int s2 = find(x[i].v); if (s1 != s2) //如果两个村庄不修路就无法联通,即元祖不同 { father[s1] = father[s2]; //把前者的元祖的father元素里存的自己改成后者的元祖 sum += x[i].dis; m++; //修成了一条路! } } printf("%d\n", sum); } return 0; }
补上prim的解法:
#include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> using namespace std; #define INF 0x3f3f3f3f #define MAXN 1010 int cost[MAXN][MAXN]; bool vis[MAXN]; int low[MAXN]; int u, v, c; int prim(int cost[][MAXN], int n) { int ans = 0; memset(vis, false, sizeof(vis)); vis[0] = true; for(int i = 1; i < n; i++) low[i] = cost[0][i]; for(int i = 1; i < n; i++) { int minc = INF; int p = -1; for(int j = 0; j < n; j++) if((!vis[j]) && (minc > low[j])) { minc = low[j]; p = j; } if(minc >= INF) return -1; ans += minc; vis[p] = true; for(int j = 0; j < n; j++) if((!vis[j]) && (low[j] > cost[p][j])) low[j] = cost[p][j]; } return ans; } int main() { // freopen("1233.in", "r", stdin); int n; while(scanf("%d", &n), n) { int se = (n - 1) * n / 2; memset(cost, 0x3f, sizeof(cost)); for(int i = 0; i < se; i++) { scanf("%d%d%d", &u, &v, &c); cost[u-1][v-1] = c; cost[v-1][u-1] = c; } printf("%d\n", prim(cost, n)); } return 0; }
相关文章推荐
- hdoj1233-还是畅通工程(并查集-kruskal && prim)
- HDOJ 1233 还是畅通工程 【最小生成树】+【prim】
- 并查集入门--hd 1233 还是畅通工程 【klckr prim】
- HDU--1233:还是畅通工程 (并查集 & 最小生成树Prim)
- HDOJ 1233 还是畅通工程 最小生成树 kruskal && prim
- hdu 1233 还是畅通工程 (最小生成树,prim,优先队列,kruskal并查集)
- hdoj 1233 还是畅通工程【最小生成树 kruskal && prim】
- HDOJ 1233 还是畅通工程(并查集)
- HDU1233 还是畅通工程(模版题(prim+kruskal)两种模版)
- hdoj 1233 还是畅通工程---最小生成树---prime算法
- HDU 1233 还是畅通工程 (并查集)
- hdu——1233还是畅通工程(并查集 求最小路径长度 减枝)
- HDU-1233 还是畅通工程(prim)
- HDU1233 还是畅通工程(并查集)
- HDOJ-1233 还是畅通工程
- HDU--1233 -- 还是畅通工程 [kruskal算法] [prime算法] [并查集]
- HDU 1233 还是畅通工程(并查集)
- HDOJ 1233 还是畅通工程
- HDU 1233.还是畅通工程【最小生成树 kruskal算法(并查集)+prim算法】【1月8】
- hdoj1233 还是畅通工程