POJ 1679 The Unique MST
2013-12-04 23:55
405 查看
题意:给一个图,判断它的最小生成树唯一不唯一。
解法:首先,容易想到一个O(n^3)或者说O(m*n^2)的方法。就是首先,求一遍最小生成树,记权值和为x1,然后枚举最小生成树中的每一条边,在不用该边的情况下求出的最小生成树权值和为x2,若枚举到某条边的时候x1 = x2,则最小生成树不唯一。若全不相等,则唯一。
但是,觉得这个方法太慢了,上网搜索了一下搜到了这篇文章,https://www.byvoid.com/blog/2-sp-mst,求次小生成树。(这道题相当于判定最小生成树和次小生成树权值和是否相等)
上面那篇文章的方法,中心思想在于:枚举每条不在最小生成树中的边,若将它加入最小生成树,一定会生成环,去掉环中的最长边,则是新的最小生成树,若去掉的边权值和加入的边权值相同,则最小生成树和次小生成树权值和相同。当然,这样写的话,时间复杂度也可能打到O(n^3),但是,基于这个思想,能有O(n^2 + m)的写法。
O(n^2+m)的写法为,从每个节点i遍历整个最小生成树,定义f[j]为最小生成树上从i到j的边中权值最大边的权值,然后遍历所有不在最小生成树中的边(i, k)比较w(i, k)和f[k]的大小,若相等则最小生成树不唯一。
tag:MST,次小生成树
解法一O(n^3):
View Code
解法:首先,容易想到一个O(n^3)或者说O(m*n^2)的方法。就是首先,求一遍最小生成树,记权值和为x1,然后枚举最小生成树中的每一条边,在不用该边的情况下求出的最小生成树权值和为x2,若枚举到某条边的时候x1 = x2,则最小生成树不唯一。若全不相等,则唯一。
但是,觉得这个方法太慢了,上网搜索了一下搜到了这篇文章,https://www.byvoid.com/blog/2-sp-mst,求次小生成树。(这道题相当于判定最小生成树和次小生成树权值和是否相等)
上面那篇文章的方法,中心思想在于:枚举每条不在最小生成树中的边,若将它加入最小生成树,一定会生成环,去掉环中的最长边,则是新的最小生成树,若去掉的边权值和加入的边权值相同,则最小生成树和次小生成树权值和相同。当然,这样写的话,时间复杂度也可能打到O(n^3),但是,基于这个思想,能有O(n^2 + m)的写法。
O(n^2+m)的写法为,从每个节点i遍历整个最小生成树,定义f[j]为最小生成树上从i到j的边中权值最大边的权值,然后遍历所有不在最小生成树中的边(i, k)比较w(i, k)和f[k]的大小,若相等则最小生成树不唯一。
tag:MST,次小生成树
解法一O(n^3):
/* * Author: Plumrain * Created Time: 2013-12-04 19:35 * File Name: G-POJ-1679-2.cpp */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define CLR(x) memset(x, 0, sizeof(x)) #define CLR1(x) memset(x, -1, sizeof(x)) #define PB push_back struct Pat{ int s, e, w; }; int n, m; Pat p[10005]; bool vis[105][105]; int d[105][105], f[105]; int cnt[105]; vector<int> nod[105]; bool cmp(Pat a, Pat b) { return a.w < b.w; } void init() { CLR (vis); CLR1 (d); scanf ("%d%d", &n, &m); for (int i = 0; i < m; ++ i){ scanf ("%d%d%d", &p[i].s, &p[i].e, &p[i].w); -- p[i].s; -- p[i].e; d[p[i].s][p[i].e] = p[i].w; d[p[i].e][p[i].s] = p[i].w; } sort (p, p+m, cmp); for (int i = 0; i < n; ++ i) nod[i].clear(); } int find(int x) { if (x != f[x]) f[x] = find(f[x]); return f[x]; } int kruskal() { for (int i = 0; i < n; ++ i) f[i] = i; int cost = 0; for (int i = 0; i < m; ++ i){ int s = p[i].s, e = p[i].e, w = p[i].w; int t1 = find(s), t2 = find(e); if (t1 != t2){ f[t1] = t2; cost += w; nod[s].PB (e); nod[e].PB (s); vis[e][s] = vis[s][e] = 1; } } int tmp; for (int i = 0; i < n; ++ i){ if (!i) tmp = find(i); else if (tmp != find(i)) return -1; } return cost; } void dfs(int x, int ma) { if (cnt[x] != -1) return; cnt[x] = ma; int sz = nod[x].size(); for (int i = 0; i < sz; ++ i) if (cnt[nod[x][i]] == -1) dfs (nod[x][i], max(d[x][nod[x][i]], ma)); } int main() { int T; scanf ("%d", &T); while (T--){ init(); int ans = kruskal(); if (ans == -1){ printf ("0\n"); continue; } bool ok = 0; for (int i = 0; i < n; ++ i){ CLR1 (cnt); dfs (i, 0); for (int j = 0; j < n; ++ j) if (i != j && !vis[i][j]) if (cnt[j] == d[i][j]) ok = 1; } if (!ok) printf ("%d\n", ans); else printf ("Not Unique!\n"); } return 0; }
View Code
相关文章推荐
- POJ 1679-The Unique MST( 判断最小生成树的唯一性)
- poj 1679 The Unique MST (次小生成树)
- POJ 1679 The Unique MST
- poj1679 The Unique MST(判定次小生成树)
- POJ 1679 The Unique MST(次小生成树)
- poj 1679 The Unique MST
- POJ-1679-The Unique MST
- POJ 1679 The Unique MST (最小生成树)
- poj 1679 The Unique MST【次小生成树】【判断最小生成树的唯一性】
- POJ - 1679 The Unique MST
- poj 题目1679 The Unique MST (最小生成树,次小生成树 prim)
- poj1679——The Unique MST
- poj 1679 The Unique MST (最小生成树是否唯一)
- POJ 1679----The Unique MST(prim)
- POJ 1679 The unique MST [次小生成树]
- POJ 1679 The Unique MST【MST是否唯一,Prime算法,最好的代码】
- POJ 1679 The Unique MST(次小生成树)
- poj 1679 The Unique MST
- POJ 1679 The Unique MST(次小生成树)
- POJ 1679 The Unique MST