题目大意:给出N个点。M条边。问这N个点形成的生成树的最大权值边-最小权值边的最小值

解题思路:先排序,然后按生成树的kruscal算法进行加边,再维护一个最小权值边

加边的时候要考虑一下加下去的边是否会形成环,假设形成环的话,就把环内的最小边去掉,然后再找出这棵新的生成树的最小边

等到生成树形成的时候,由于加入进去的新边的权值肯定是最大值的,所以仅仅要仅仅减去之前维护一个的最小值就能够了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std; #define N 400
#define M 160010
#define INF 0x3f3f3f3f struct Edge{
int u, v, c;
Edge() {}
Edge(int u, int v, int c): u(u), v(v), c(c) {}
}E[M]; int f[N], dis[N][N];
int cnt, Min_Edge, n, m;
bool vis[N]; int cmp(const Edge &a, const Edge &b) {
return a.c < b.c;
} void init() {
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].c);
dis[E[i].u][E[i].v] = dis[E[i].v][E[i].u] = E[i].c;
}
} int LCA(int i) {
int u = E[i].u, v = E[i].v, c = E[i].c;
memset(vis, 0, sizeof(vis));
while (!vis[u]) {
vis[u] = true;
if (u == f[u]) break;
u = f[u];
} while (!vis[v] && f[v] != v) v = f[v];
if (!vis[v]) return -1;
return v;
} void findCycle(int i) {
int lca = LCA(i);
if (lca == -1) return ;
int u = E[i].u, v = E[i].v, c = E[i].c;
Edge MinEdge;
MinEdge.c = INF;
int fu = f[u];
while (fu != u && u != lca) {
if (dis[fu][u] < MinEdge.c) MinEdge = Edge(fu, u, dis[fu][u]); fu = f[fu];
u = f[u]; } int fv = f[v];
while (fv != v && v != lca) {
if (dis[fv][v] < MinEdge.c) MinEdge = Edge(fv, v, dis[fv][v]);
fv = f[fv];
v = f[v];
} f[MinEdge.v] = MinEdge.v;
Min_Edge = INF;
for (int i = 0; i < n; i++)
if (f[i] != i && dis[f[i]][i] < Min_Edge)
Min_Edge = dis[f[i]][i];
cnt--;
} void AddEdge(int i) {
int u = E[i].u, v = E[i].v, c = E[i].c;
if (f[u] == u) f[u] = v;
else if (f[v] == v) f[v] = u;
else {
vector<int> vec;
while (1) {
vec.push_back(u);
if (u == f[u]) break;
u = f[u];
}
int size = vec.size();
for (int i = size - 1; i > 0; i--) f[vec[i]] = vec[i - 1];
f[E[i].u] = E[i].v;
}
Min_Edge = min(Min_Edge, c);
cnt++;
} void solve() {
sort(E, E + m, cmp);
for (int i = 0; i < n; i++)
f[i] = i; int ans = INF;
Min_Edge = INF;
cnt = 0;
for (int i = 0; i < m; i++) {
findCycle(i);
AddEdge(i);
if (cnt == n - 1) ans = min(ans, E[i].c - Min_Edge); }
printf("%d\n", ans);
} int main() {
while (scanf("%d", &n) != EOF && n) {
scanf("%d", &m);
init();
solve();
}
return 0;
}

最新文章

  1. VS 2005 修复重置(深度重置)
  2. iOS:实现图片的无限轮播之使用第三方库SDCycleScrollView
  3. ubuntu server nginx 安装与配置
  4. Java跳出循环-break和continue语句
  5. 我的github今天大手笔分享,welcome——fork
  6. ReactNative常见报错
  7. linux LVM 逻辑卷
  8. Mongoose即使是简单的表查询
  9. Android Security
  10. VueJS实现一个货币结算自定义控件
  11. 微信小程序之自定义toast弹窗
  12. Firefox书签同步工具Xmarks
  13. JVM学习九:JVM之GC算法和种类
  14. TFS:需要包管理许可证才能进一步操作You need a Package Management license to go further
  15. BAT-给文件右击菜单增加7-ZIP浏览功能
  16. Linux 克隆虚拟机引起的“Device eth0 does not seem to be present, delaying initialization”
  17. mysql单列索引和联合索引的使用
  18. Xquery的初步学习(一次Lab作业的总结)
  19. 20145231熊梓宏 《网络对抗》 实验9 Web安全基础实践
  20. redhad系统配置daocloud加速器

热门文章

  1. JNI/NDK开发指南(九)——JNI调用性能測试及优化
  2. funuiTitle-居中问题修改
  3. node.js是什么
  4. Zabbix主动代理模式 + 主动模式agent客户端
  5. Windows 下 Sublime Text 默认打开方式问题解决办法
  6. 【arc062e】Building Cubes with AtCoDeer
  7. 【例题 8-7 UVA - 11572】Unique Snowflakes
  8. 【Good Bye 2017 A】New Year and Counting Cards
  9. 洛谷 P2819 图的m着色问题
  10. SJTU 3001. 二哥的幸运