POJ1861 Network(最小生成树)

来源:互联网 发布:行车记录仪软件免费版 编辑:程序博客网 时间:2024/06/08 06:23

题意:

有n个顶点,m条边,每条边双向的,并且有一定的长度,现在要求使每个顶点连通起来,并且使总长度最短输出最大边,和边的总数,还有是这些边的情况输出

要点:

这破题,special judge给的输出例子是错的,导致我先用prim算法搞了一个小时还是WA,怒换Kruskal算法10分钟AC了。不过用这题也算理解了special judge的意思,就是有很多种正确输出,只要选一种输出就行。后来发现我的prim算法模板有点问题,要先将map赋予一个比较大的值,否则比较最小值会出错,而且这题要求双向边,我之前没彻底理解prim。


Kruskal算法:

15346658Seasonal1861Accepted360K63MSC++1063B2016-04-03 10:04:01

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>#define maxn 1005using namespace std;int p[maxn],a[maxn],b[maxn];int m, n,num;struct edge{int u, v, len;}e[maxn*maxn];bool cmp(edge a, edge b){return a.len < b.len;}void init(){for (int i = 1; i <= m; i++)p[i] = i;}int find(int x){if (p[x] == x) return x;return p[x] = find(p[x]);}bool merge(int x, int y){x = find(x);y = find(y);if (x != y){p[x] = y;return true;}return false;}int kruskal(){init();sort(e, e + n, cmp);int max = -1, edges = 0;num = 0;for (int i = 0; i < n; i++){if (merge(e[i].u, e[i].v)){if (max < e[i].len)max = e[i].len;a[num] = e[i].u; b[num++] = e[i].v;edges++;}if (edges + 1 == m)return max;}return -1;}int main(){int x, y, temp;scanf("%d%d", &m, &n);for (int i = 0; i < n; i++)scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].len);printf("%d\n", kruskal());printf("%d\n", num);for (int i = 0; i < num; i++)printf("%d %d\n", a[i], b[i]);return 0;}

Prim算法:

15346706Seasonal1861Accepted4124K125MSC++1060B2016-04-03 10:26:43

#include<stdio.h>#include<string.h>#include<stdlib.h>int map[1005][1005], low[1005], pre[1005];int m, n, num,max;bool vis[1005];int a[1005], b[1005];void prim(){int i, j, min, mark;num = 0; max = 0;memset(vis, false, sizeof(vis));for (i = 2; i <= m; i++){low[i] = map[1][i];pre[i] = 1;//用pre数组记录前驱}vis[1] = true;for (i = 1; i < m; i++){min = 0xffffff;for (j = 1; j <= m; j++)if (!vis[j] && low[j] < min){min = low[j];mark = j;}if (max < min)max = min;vis[mark] = true;a[num] = pre[mark]; b[num++] = mark;for (j = 1; j <= m; j++)if (!vis[j] && map[mark][j] < low[j]){low[j] = map[mark][j];pre[j] = mark;//此时前驱更新为mark}}}int main(){int x, y, temp;scanf("%d%d", &m, &n);for (int i = 1; i <= m; i++)for (int j = 1; j <= m; j++)map[i][j] = 0xfffff;//一开始要先赋予一个较大值for (int i = 0; i < n; i++){scanf("%d%d%d", &x, &y, &temp);map[x][y] = temp;map[y][x] = temp;//要双向边}prim();printf("%d\n%d\n", max,num);for (int i = 0; i < num; i++)printf("%d %d\n", a[i], b[i]);return 0;}



0 0
原创粉丝点击