【题目描述】
给定一个标号为从 1 到 n的、有 m 条边的无向图,求边权最大值与最小值的差值最小的生成树。
【输入格式】
第一行两个数 n,m,表示图的点和边的数量。
第二行起 m 行,每行形如 ui, vi, wi,代表 ui到 vi 间有一条长为 wi 的无向边。
【输出格式】
输出一行一个整数,代表你的答案。
数据保证存在至少一棵生成树。
S a m p l e I n p u t Sample~~Input Sample Input
4 6
1 2 10
1 3 100
1 4 90
2 3 20
2 4 80
3 4 40
S a m p l e O u t p u t Sample~~Output Sample Output
20
【题意分析】
好久没打LCT了,提升码力。
我们先对边权排个序,然后依次从小到大加入生成树里。
用并查集维护连通性:如果新加的两条边还不在连通块里,就link一下,用一个set维护现在在生成树里面所有的边。link的时候在set里面插入当前边。
如果新加的两条边已经构成连通块(已经有最小生成树结构了),考虑贪心,将set里面存的最小的边删去(因为加入的边越来越大,而且题目要求的是最小差值,因此贪心删去最小的边)然后加入当前边。
怎么删?LCT提取链上信息split(x,y),信息就存在y里面了,两次cut即可。
LCT里面存的是最小边值,并且有辅助数组存下最小边值所在位置。只要修改一下maintain函数,其他把LCT板子打一遍就行
set内部用pair。
Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <set>
#include <algorithm>
#define mp make_pair
#define INF 0x3f3f3f3f
#define MAXN 500000
using namespace std;
typedef pair <int, int> pii;
struct Node {
int u, v, val;
}edge[MAXN];
set <pii> data;
int son[MAXN][2], tmin[MAXN], pos[MAXN], father[MAXN], stack[MAXN];
int val[MAXN], f[MAXN], cnt, tot, ans = INF, n, m;
bool rev[MAXN];
inline int read () {
register int s = 0, w = 1;
register char ch = getchar ();
while (! isdigit (ch)) {
if (ch == '-') w = -1; ch = getchar ();}