poj 3522 && uva 1395 && la 3887
来源:互联网 发布:算法流程图怎么画 编辑:程序博客网 时间:2024/06/06 04:30
题目概述
有N个点,M条边,问是否可构成一生成树,若可,求最长边与最短边差值的最小值
没有自环或平行边
时限
5000ms/15000ms
输入
第一行整数N,M,其后M行,每行三个整数a,b,c,描述a,b之间有一条边,权值为c,输入到N=M=0结束
限制
2<=N<=100
输出
每行一个数,若无生成树,为-1,否则为差值最小值
样例输入
4 5
1 2 3
1 3 5
1 4 6
2 4 6
3 4 7
4 6
1 2 10
1 3 100
1 4 90
2 3 20
2 4 80
3 4 40
2 1
1 2 1
3 0
3 1
1 2 1
3 3
1 2 2
2 3 5
1 3 6
5 10
1 2 110
1 3 120
1 4 130
1 5 120
2 3 110
2 4 120
2 5 130
3 4 120
3 5 110
4 5 120
5 10
1 2 9384
1 3 887
1 4 2778
1 5 6916
2 3 7794
2 4 8336
2 5 5387
3 4 493
3 5 6650
4 5 1422
5 8
1 2 1
2 3 100
3 4 100
4 5 100
1 5 50
2 5 50
3 5 50
4 1 150
0 0
样例输出
1
20
0
-1
-1
1
0
1686
50
讨论
图论,最小生成树,kruskal算法,按原题说是最瘦生成树,首先有一点要明白,按权值排序之后,数组中相邻的两条边权值差最小,那么要想使得差最小就要从数组中连续取边构成树,这样才能保证第一条边和最后一条边离的比较近,也就是差比较小,但同时也不难发现,这样会产生多个树,差也不同,因此需要枚举树的第一条边,从这条边开始取边,最后得到最小的差值
实现层面上,由于已经排序过,不需要优先队了,这样kruskal算法主体复杂度下降到与边数相关的线性级,由于是枚举的第一条边,最终复杂度是与边相关的平方级,边数也不是很多,总之是足够了
题解状态
224K,63MS,C++,1239B
题解代码
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define INF 0x3f3f3f3f#define MAXN 103#define memset0(a) memset(a,0,sizeof(a))struct Edge//边的结构{ int from, to, w;//起点 终点 权值 bool operator<(const Edge &b)const { return w < b.w; }}graph[4953];//完全图时 100*99/2=4950int N, M;//点总数 边总数int least, most, sub, id[MAXN];//最小权 最大权 差值 并查集的父节点数组int UFfind(int a)//并查集的查根 这可比递归快多了{ while (a != id[a]) a = id[a]; return a;}bool kruskal(int p)//kruskal算法主体 参数是开始的边的下标{ int cnt = N; for (int p = 1; p <= N; p++) id[p] = p; int a, b; for (int i = p; i < M&&cnt != 1; i++) if ((a = UFfind(graph[i].from)) != (b = UFfind(graph[i].to))) { cnt--; id[a] = b; least = min(least, graph[i].w); most = max(most, graph[i].w); if (most - least > sub)//当差值已经大于之前的最优情况时就没比要再算了 return 1;//直接视为构成了生成树返回即可 } return cnt == 1;//如果并查集有多个 则是不成树}int fun(){ for (int p = 0; p < M; p++) scanf("%d%d%d", &graph[p].from, &graph[p].to, &graph[p].w);//input sort(graph, graph + M);//一次排序足矣 sub = INF;//如果不初始化为INF 中途会因为剪枝而提前返回错误结果 most = least = graph[0].w; if (!kruskal(0))//第一次运行检查是否可成树 return -1; sub = most - least;//顺手初始化差值 for (int p = 1; p < M; p++) { least = most = graph[p].w; if (kruskal(p))//只有成树了才取最小 sub = min(sub, most - least); } return sub;}int main(void){ //freopen("vs_cin.txt", "r", stdin); //freopen("vs_cout.txt", "w", stdout); while (~scanf("%d%d", &N, &M) && (N || M))//input printf("%d\n", fun());//output}
EOF
- poj 3522 && uva 1395 && la 3887
- poj 1873 && uva 811 && la 5211
- poj 1042 && uva 757 && la 5422
- poj 1017 && uva 311 && la 5526
- poj 1328 && uva 1193 && la 2519
- POJ 1901 | LA 2963 | UVa 1325 - Hypertransmission (思维 扫描)
- uva 1423 LA 4255
- uva 1265 (LA 4848)
- UVa LA 3026 Period
- UVa 1330 LA 3029
- uva 1450 LA 4725
- Poj 3154(LA 3708)
- poj 1287 && la 2515
- LA 3902 UVA 1267 - Network
- UVA 1450 LA 4725 Airport
- UVA LA 4670(AC自动机)
- LA 2678 UVA 1121 - Subsequence
- UVa LA 4670 Dominating Patterns
- Linux 文件(vi/vim)与目录管理
- 带你读开源—ASP.NET_MVC(三)
- Python设计模式(四)【桥接模式】
- 条款2:尽量以const,enum,inline替换#define
- Jquery选择器总结
- poj 3522 && uva 1395 && la 3887
- android 解决eclipse调试时出现INSTALL_FAILED_UPDATE_INCOMPATIBLE
- 智力题
- 【bzoj1088】 [SCOI2005]扫雷Mine
- 深度探索c++对象模型——读书笔记(二)
- Qualcomm thermal的介绍
- Android原生API搞定圆角、圆形图片
- JSP省市区三级联动下拉选
- 变量作用域