每日一题(12)——计算Slim Span(并查集)

2023-10-29 22:32
文章标签 计算 每日 查集 span slim

本文主要是介绍每日一题(12)——计算Slim Span(并查集),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先总结一下并查集:

其中按秩合并分为:按树的深度和树的大小合并,效果都相同。

 

 

 

 

 

问题ID:POJ3522

Slim Span
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 5098 Accepted: 2671

Description

Given an undirected weighted graph G, you should find one of spanning trees specified as follows.

The graph G is an ordered pair (V, E), where V is a set of vertices {v1,v2, …,vn} andE is a set of undirected edges {e1,e2, …,em}. Each edgeeE has its weightw(e).

A spanning tree T is a tree (a connected subgraph without cycles) which connects all the n vertices withn − 1 edges. The slimness of a spanning treeT is defined as the difference between the largest weight and the smallest weight among then − 1 edges ofT.


Figure 5: A graph G and the weights of the edges

For example, a graph G in Figure 5(a) has four vertices {v1,v2,v3,v4} and five undirected edges {e1,e2,e3,e4,e5}. The weights of the edges arew(e1) = 3,w(e2) = 5,w(e3) = 6,w(e4) = 6,w(e5) = 7 as shown in Figure 5(b).


Figure 6: Examples of the spanning trees of G

There are several spanning trees for G. Four of them are depicted in Figure 6(a)~(d). The spanning treeTa in Figure 6(a) has three edges whose weights are 3, 6 and 7. The largest weight is 7 and the smallest weight is 3 so that the slimness of the treeTa is 4. The slimnesses of spanning treesTb,Tc andTd shown in Figure 6(b), (c) and (d) are 3, 2 and 1, respectively. You can easily see the slimness of any other spanning tree is greater than or equal to 1, thus the spanning tree Td in Figure 6(d) is one of the slimmest spanning trees whose slimness is 1.

Your job is to write a program that computes the smallest slimness.

Input

The input consists of multiple datasets, followed by a line containing two zeros separated by a space. Each dataset has the following format.

nm 
a1b1w1
  
ambmwm

Every input item in a dataset is a non-negative integer. Items in a line are separated by a space. n is the number of the vertices and m the number of the edges. You can assume 2 ≤n ≤ 100 and 0 ≤mn(n − 1)/2.ak andbk (k = 1, …,m) are positive integers less than or equal ton, which represent the two verticesvak andvbk connected by thekth edgeek.wk is a positive integer less than or equal to 10000, which indicates the weight ofek. You can assume that the graphG = (V,E) is simple, that is, there are no self-loops (that connect the same vertex) nor parallel edges (that are two or more edges whose both ends are the same two vertices).

Output

For each dataset, if the graph has spanning trees, the smallest slimness among them should be printed. Otherwise, −1 should be printed. An output should not contain extra characters.

Sample Input

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

Sample Output

1
20
0
-1
-1
1
0
1686
50

 

 

 

此题对kruskal算法做了变形,不是求最小生成树,而是求最大边权值与最小边权值之差最小的生成树,同样可以用kruskal算法的实现方法,采用并查集。如果求最小生成树要将边加入到堆中,并且不需要遍历所有的生成树情况

//此题对kruskal算法做了变形,不是求最小生成树
//而是求最大边权值与最小边权值之差最小的生成树
//同样可以用kruskal算法的实现方法,采用并查集
#include <iostream>
#include <stdlib.h>
#include <algorithm>
#define inf 10000000//边权值的上界;
using namespace std;
int m,n;
//p数组用于记录父节点,r数组用于统计以r为根的子
//树中间有多少个点,其实r数组可以取消,因为
//直接由根节点的绝对值就可以这个集合中的元素个数;
int p[105];
int r[105];
struct edge{
int u;
int v;
int w;
}e[5000];
bool cmp(const edge & e1,const edge & e2){
return e1.w < e2.w;
}
void set_init(){		//并查集初始化;
for (int i = 1;i <= n;i++)
{
p[i] = i;
r[i] = 1;//初始状态每个的根是自己,集合个数为1
}
}
// int set_find(int x){//查找包含x的集合树的根
// 	while (p[x] >= 0)
// 	{
// 		x = p[x];
// 	}
// 	return x;
// }
//以上为非递归实现,递归实现如下
int set_find(int x){
if(p[x] == x) return x;
else  p[x] = set_find(p[x]);
return p[x];
}
// void set_union(int root1,int root2){//将两个集合合并
// 	p[root1]+=p[root2];
// 	p[root2] = root1;//用根root2连接到root1下面
// }
//为防止树的退化,改进版的union操作如下
void set_union(int x,int y){//将两个集合合并
if(r[x] <= r[y]){
p[x] = y;
r[y]+=r[x];//y作为根
}
else {
p[y] = x;
r[x]+=r[y];
}
}
int main(){
int i,j,k,ans,px,py,a,b,temp;
while (cin>>n>>m)
{
if (n == 0 && m == 0)
break;
for (i = 0;i < m;i++)
{
cin>>e[i].u>>e[i].v>>e[i].w;
}
if ( n == 2 && m == 1)
{
cout<<"0"<<endl;//2点1边的情况单独处理
continue;
}
sort(e,e+m,cmp);
ans = inf;
for (i = 0; i<m;i++)
{
k = 0;
set_init();
for (j = i;j<m;j++)
{
px = set_find(e[j].u);
py = set_find(e[j].v);
if (px != py)
{
set_union(px,py);//注意这里只是求生成树,不一定是mst,只要不在同一个集合中就可以选这条边,两个端点变成同一个集合内
k++;
if(k == 1){//这是最小的边
a = e[j].w;
}
else if (k == n-1)//这是最大的边也是最后一条边
{
b = e[j].w;
temp = b - a;
if (temp < ans)
{
ans = temp;
}
break;
}
}
}
}
if (ans == inf)
{
cout<<"-1"<<endl;
}
else cout<<ans<<endl;
}
return 0;
}


 

 

 

这篇关于每日一题(12)——计算Slim Span(并查集)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/303801

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i