例题11-2 苗条的生成树 UVa1395

1.题目描述:点击打开链接

2.解题思路:本题实质上还是利用Kruskal算法来生成MST。首先按照边权值由小到大排序,对于一个连续的边集[L,R],如果使得这n个点全部连通,则一定存在一个苗条度不超过w[R]-w[L]的生成树。因此,可以从小到大枚举L,对于每一个L,利用Kruskal算法生成最小生成树后,计算苗条度,用ans取最小的即可。如果枚举结束后ans依然是INF。那么输出-1。这里可以加上一个预处理:如果m<n-1,那么直接输出-1。

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

#define N 5000+10
#define INF 100000000
int u[N], v[N], w[N];
int r[N], p[N];
int n, m;
int find(int x)
{
	return p[x] == x ? x : p[x] = find(p[x]);
}
int cmp(const int i, const int j)
{
	return w[i] < w[j];
}
int Kruskal(int L)
{
	int ans = -1;
	int R;
	for (int i = 1; i <= n; i++)//初始化并查集
		p[i] = i;
	for (R = L; R < m; R++)
	{
		int e = r[R];
		int x = find(u[e]);
		int y = find(v[e]);
		if (x != y)
		{
			ans = max(ans, w[e] - w[r[L]]);
			p[x] = y;
		}
	}
	int fa = find(1);
	for (int i = 1; i <= n; i++)//判断n个点是否都连通
	if (fa != find(i))
		return ans=INF;
	return ans;

}
int main()
{
	//freopen("test.txt", "r", stdin);
	while (cin >> n >> m && (n || m))
	{
		int ans = INF;
		for (int i = 0; i < m; i++)
			scanf("%d%d%d", &u[i], &v[i], &w[i]);
		for (int i = 0; i < m; i++)
			r[i] = i;
		sort(r, r + m, cmp);
		if (m < n - 1)printf("-1\n");
		else
		{
			for (int i = 0; i < m - n + 2; i++)
				ans = min(ans, Kruskal(i));
			if (ans == INF)
				printf("-1\n");
			else printf("%d\n", ans);
		}
	}
	return 0;
}
时间: 2024-07-31 10:39:54

例题11-2 苗条的生成树 UVa1395的相关文章

UVa 1395 苗条的生成树(Kruskal+并查集)

https://vjudge.net/problem/UVA-1395 题意: 给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树. 思路: 主要还是克鲁斯卡尔算法,先仍是按权值排序,对于一个连续的边集区间[L,R],如果这些边使得n个点全部连通,则一定存在一个苗条度不超过W[R]-W[L]的生成树.从小到大枚举L,对于每个L,从小到大枚举R. 这道题目我一直超时,最后发现数组开小了,我一直以为数组开小了肯定会出来Runtime error的... 1 #include<iostr

ACM主要内容

转自:http://blog.csdn.net/hnuzengchao/article/details/7283609 1:数学 1.1:数论 1.1.1:中国剩余定理1.1.2:欧拉函数1.1.3:欧几里得定理 1.1.3.1:欧几里得定理 1.1.3.2:扩展欧几里得 1.1.4:大数分解与素数判定1.1.5:佩尔方程 1.2:组合数学 1.2.1:排列组合1.2.2:容斥原理1.2.3:递推关系和生成函数1.2.4:Polya计数法1.2.4.1:Polya计数公式1.2.4.2:Burn

《算法竞赛入门经典——训练指南》第二章题库

UVa特别题库 UVa网站专门为本书设立的分类题库配合,方便读者提交: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=442 注意,下面注有"extra"的习题并没有在书中出现,但在上面的特别题库中有,属于附加习题. 基础练习 (Basic Problems) UVa11388 GCD LCM UVa11889 Benefit UVa10943 How do y

3.3 字符串(1)

Trie 前缀树 字典树 例题11  LA 3942 http://acm.hust.edu.cn/vjudge/problem/22109 字典树第一个例题我用set水过,先记录这个版本吧,题意是,给一个串,还有一些短串的集合,问有多少种不同的拆分方法使得拆分完后,每个子串都在集合中. dp[len] 表示前len个有多少拆分法 dp[0]=1, 前0个字符有一种拆分法,空嘛.  dp[len] 就是答案,  转移就是, 如果接下来一段在集合中,那么就可以转移到长度加这段的长度. 起点有la=

java cmd常用命令

熟悉Java的常用命令 面试例题11:使用jar命令. 请使用jar命令,将test文件夹压缩成.jar文件,并简述其压缩包的结构. 考点:对于Java程序员来说,更多情况下是使用集成Java开发工具,例如JBuilder.Eclipse等,而对于最基本的Java编译和常见的命令行工具往往都不熟悉,这个面试例题主要考查求职者对于Java命令行基本工具的使用,从而了解求职者对Java编程的熟悉程度. 出现频率:★★★ 解析 熟练的Java开发者应该掌握常用的Java命令行工具.求职者应该熟练掌握j

思科CCNA第三学期第五章答案

1.请参见图示. 从图中所示的输出可得出什么结论? 在 Fa0/2 和 Fa0/4 之间通信的两台主机的开销为 38. 已经静态配置了优先级,目的在于确定根. 此交换机上禁用了 STP. 已经更改了计时器,目的在于缩短收敛时间. 2.请参见图示.服务器发送了一个 ARP 请求,询问其默认网关的 MAC 地址.如果未启用 STP,则此 ARP 请求的结果是什么? Router_1 会丢弃该广播并使用下一跳路由器的 MAC 地址来回应. Switch_A 会使用 Router_1 的 E0 接口的

1.2 变量及输入

要完成人与计算机的交互,有输出就得有输入.c++中输入输出最基本的是cout,cin.c中是printf和scanf.下面关于是scanf的用法: 1-4 a + b问题 1 #include<stdio.h> 2 int main() 3 { 4 int a, b; 5 scanf("%d%d", &a, &b); 6 printf("%d", a + b); 7 8 return 0; 9 } a, b是变量,c系列是一种强类型计算机

三极管原理,开关电路设计原则,NPN、PNP区别及常用三极管参数

三极管的工作原理 三极管是电流放大器件,有三个极,分别叫做集电极C,基极B,发射极E.分成NPN和PNP两种.我们仅以NPN三极管的共发射极放大电路为例来说明一下三极管放大电路的基本原理. 一.电流放大 下面的分析仅对于NPN型硅三极管.如上图所示,我们把从基极B流至发射极E的电流叫做基极电流Ib:把从集电极C流至发射极E的电流叫做集电极电流 Ic.这两个电流的方向都是流出发射极的,所以发射极E上就用了一个箭头来表示电流的方向.三极管的放大作用就是:集电极电流受基极电流的控制(假设电源 能够提供

百度回复将按时缴费卡水立方

http://www.ebay.com/cln/ch.y908/-/176925541016/2015.02.11 http://www.ebay.com/cln/shaamjson/-/176833416018/2015.02.11 http://www.ebay.com/cln/x_ru421/-/176666486019/2015.02.11 http://www.ebay.com/cln/hua6592_18usz/-/176835881012/2015.02.11 http://www