HDU 5624 KK's Reconstruction(暴力 + MST)
2016-02-10 20:58
375 查看
题意:
N≤2000个点,M≤15000条边,求所有MST中最大边−最小边的最小值,无MST输出−1
分析:
模拟MST生成的过程,根据Kruskal算法的正确性
从小往大加边,如果某条边形成环了,就删去环上的最小边把这条边丢进去
生成MST时就更新答案,尝试完所有边就是ans
时间复杂度为O(mlogm+nm)
代码:
如果数据范围小的话,可以跑m遍Kruskal,易写,时间复杂度为O(mlogm+m2)
代码:
N≤2000个点,M≤15000条边,求所有MST中最大边−最小边的最小值,无MST输出−1
分析:
模拟MST生成的过程,根据Kruskal算法的正确性
从小往大加边,如果某条边形成环了,就删去环上的最小边把这条边丢进去
生成MST时就更新答案,尝试完所有边就是ans
时间复杂度为O(mlogm+nm)
代码:
// // Created by TaoSama on 2016-02-10 // Copyright (c) 2016 TaoSama. All rights reserved. // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, m; struct Edge { int u, v, c; bool operator<(const Edge& e) const { return c < e.c; } bool operator==(const Edge& e) const { return u == e.u && v == e.v && c == e.c; } } edge[15005]; Edge minEdge; vector<Edge> G[2005]; bool dfs(int u, int fa, int t, multiset<int>& s) { if(u == t) return true; for(Edge& e : G[u]) { int v = e.v; if(v == fa) continue; if(dfs(v, u, t, s)) { minEdge = min(minEdge, e); return true; } } return false; } void del(multiset<int>& s) { int u = minEdge.u, v = minEdge.v, c = minEdge.c; s.erase(s.find(c)); G[u].erase(find(G[u].begin(), G[u].end(), minEdge)); swap(minEdge.u, minEdge.v); G[v].erase(find(G[v].begin(), G[v].end(), minEdge)); } int p[2005]; int find(int x) { return p[x] = p[x] == x ? x : find(p[x]); } bool unite(int u, int v) { u = find(u), v = find(v); if(u == v) return false; p[u] = v; return true; } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i) { int u, v, c; scanf("%d%d%d", &u, &v, &c); edge[i] = (Edge) {u, v, c}; } sort(edge + 1, edge + 1 + m); multiset<int> s; for(int i = 1; i <= n; ++i) { p[i] = i; G[i].clear(); } int ans = 2e9, cnt = 0; for(int i = 1; i <= m; ++i) { int u = edge[i].u, v = edge[i].v, c = edge[i].c; if(unite(u, v)) ++cnt; else { minEdge.c = 2e9; dfs(u, -1, v, s); del(s); } s.insert(c); G[u].push_back((Edge) {u, v, c}); G[v].push_back((Edge) {v, u, c}); if(cnt == n - 1) ans = min(ans, c - *s.begin()); } if(ans == 2e9) ans = -1; printf("%d\n", ans); } return 0; }
如果数据范围小的话,可以跑m遍Kruskal,易写,时间复杂度为O(mlogm+m2)
代码:
// // Created by TaoSama on 2016-02-06 // Copyright (c) 2016 TaoSama. All rights reserved. // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, m; struct Edge { int u, v, c; void read() {scanf("%d%d%d", &u, &v, &c);} bool operator<(const Edge& e) const { return c < e.c; } } edge ; int p ; int find(int x) { return p[x] = p[x] == x ? x : find(p[x]); } bool unite(int x, int y) { x = find(x), y = find(y); if(x == y) return false; p[x] = y; return true; } int kruskal(int i) { if(m - i + 1 < n - 1) return 0x7fffffff; int ret = -edge[i].c, cnt = 0, maxv = 0; for(int j = 1; j <= n; ++j) p[j] = j; for(int j = i; j <= m; ++j) { int u = edge[j].u, v = edge[j].v; cnt += unite(u, v); if(cnt == n - 1) { ret += edge[j].c; break; } } if(cnt != n - 1) return 0x7fffffff; return ret; } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i) edge[i].read(); sort(edge + 1, edge + 1 + m); int ans = 0x7fffffff; for(int i = 1; i <= m; ++i) { ans = min(ans, kruskal(i)); } if(ans == 0x7fffffff) ans = -1; printf("%d\n", ans); } return 0; }
相关文章推荐
- java实现 聚类算法之MST算法
- 用fail2ban阻止SSH和VSFTP暴力破解密码
- 2015BJOI day1第三题 糖果candy
- 4495: Least Prime factor 找到最小质因子P的第N小正整数
- 暴力枚举法求最大连续和
- poj2395 解题报告
- 最小生成树 : Kruskal 算法
- 最小生成树 : Prim 算法
- STP 4 - MST 和 PVST 对比 (侧重MST)
- POJ3026 - Borg Maze [MST]
- CodeForces 241F Race
- HDU 4313 Matrix
- [BZOJ2594][WC2006][LCT][MST]水管局长数据加强版
- POJ 2965.The Pilots Brothers' refrigerator
- POJ 1753.Flip Game
- POJ 3295.Tautology
- hdu 5533 Dancing Stars on Me
- hdu5532Almost Sorted Array
- 没参加的2015百度之星——数矩形
- poj 3279 Fliptile