POJ1679 The Unique MST 题解 次小生成树 题解 Kruskal+暴力LCA解法(因为倍增不会写)

题目链接:http://poj.org/problem?id=1679

题目大意:
给你一个简单连通图,判断他的最小生成树是否唯一。

解题思路:

首先(我这里用Kruskal算法)求出它的最小生成树(以下简称MST)以及对应的边,然后构造出这棵MST。

然后我们枚举图上每一条不在此MST上的边,假设这条边的两个端点是 \(u\) 和 \(v\),边权为 \(w\) ,求MST上 \(u\) 到 \(v\) 的树链上的最大边的值是否等于 \(w\),如果等于 \(w\) 就说明 MST 不唯一。

这一部分可以用树上倍增算法解决,但是我暂时还不会写,所以我就暴力做了囧。

所以我这样写的时间复杂度是:

Kruskal算法的 \(O(m \log m)\) + 枚举每一条边+LCA的 \(O(mn)\) = \(O(m \log m + mn)\) 。

实现代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 110, maxm = 10010;
int T, n, m, f[maxn], p[maxn], pe[maxn], ans, dep[maxn];
struct Edge {
    int u, v, w;
    bool choose;
    Edge () { choose = false; };
    Edge (int _u, int _v, int _w) { u = _u; v = _v; w = _w; choose = false; }
} edge[maxm];
vector<Edge> g[maxn];
void init() {
    ans = 0;
    for (int i = 1; i <= n; i ++) {
        g[i].clear();
        f[i] = i;
    }
}
int func_find(int x) {
    if (x == f[x]) return x;
    return f[x] = func_find(f[x]);
}
void func_union(int x, int y) {
    int a = func_find(x), b = func_find(y);
    f[a] = f[b] = f[x] = f[y] = min(a, b);
}
inline bool cmp(Edge a, Edge b) {
    return a.w < b.w;
}
void kruskal() {
    int cnt = 0;
    sort(edge, edge+m, cmp);
    for (int i = 0; i < m; i ++) {
        int u = edge[i].u, v = edge[i].v, w = edge[i].w;
        if (func_find(u) != func_find(v)) {
            edge[i].choose = true;
            func_union(u, v);
            ans += w;
            g[u].push_back(Edge(u, v, w));
            g[v].push_back(Edge(v, u, w));
            cnt ++;
            if (cnt >= n-1) break;
        }
    }
}
void dfs(int u, int d) {
    dep[u] = d;
    int sz = g[u].size();
    for (int i = 0; i < sz; i ++) {
        int v = g[u][i].v, w = g[u][i].w;
        if (v == p[u]) continue;
        p[v] = u;
        pe[v] = w;
        dfs(v, d+1);
    }
}
int find_chain(int u, int v) {
    int maxw = 0;
    while (u != v) {
        if (dep[u] > dep[v]) {
            maxw = max(maxw, pe[u]);
            u = p[u];
        }
        else {
            maxw = max(maxw, pe[v]);
            v = p[v];
        }
    }
    return maxw;
}
int main() {
    scanf("%d", &T);
    while (T --) {
        scanf("%d%d", &n, &m);
        init();
        for (int i = 0; i < m; i ++)
            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
        kruskal();
        dep[1] = 1;
        dfs(1, 1);
        bool is_unique = true;
        for (int i = 0; i < m; i ++) {
            if (!edge[i].choose) {
                int u = edge[i].u, v = edge[i].v, w = edge[i].w;
                if (find_chain(u, v) == w) {
                    is_unique = false;
                    break;
                }
            }
        }
        if (is_unique) printf("%d\n", ans);
        else puts("Not Unique!");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/quanjun/p/12253091.html

时间: 2024-08-03 02:00:10

POJ1679 The Unique MST 题解 次小生成树 题解 Kruskal+暴力LCA解法(因为倍增不会写)的相关文章

poj1679——The Unique MST(次小生成树,Kruskal)

Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the followin

POJ1679 The Unique MST 【次小生成树】

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20421   Accepted: 7183 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ1679 The Unique MST(次小生成树)

可以依次枚举MST上的各条边并删去再求最小生成树,如果结果和第一次求的一样,那就是最小生成树不唯一. 用prim算法,时间复杂度O(n^3). 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define MAXN 111 5 #define INF (1<<30) 6 struct Edge{ 7 int u,v; 8 }edge[MAXN]; 9 int NE; 10 11 int n

POJ - 1679 The Unique MST (次小生成树)

Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the followin

POJ 1679:The Unique MST(次小生成树&amp;&amp;Kruskal)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19941   Accepted: 6999 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

poj 1679 The Unique MST【次小生成树】

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24034   Accepted: 8535 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ 1679 The Unique MST:次小生成树【倍增】

题目链接:http://poj.org/problem?id=1679 题意: 给你一个图,问你这个图的最小生成树是否唯一. 题解: 求这个图的最小生成树和次小生成树.如果相等,则说明不唯一. 次小生成树(倍增算法): maxn[k][i]:表示从节点i向上走2^k步,这一段中边权的最大值. 枚举每一条不在MST中的边,求出这条边两端点之间在MST上路径上的最大边权mx. 次小生成树(非严格) = max(MST - mx + len) AC Code: 1 #include <iostream

POJ 1679:The Unique MST(次小生成树&amp;amp;&amp;amp;Kruskal)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19941   Accepted: 6999 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

poj 1679 The Unique MST,次小生成树

次小生成树 求最小生成树时,用数组Max[i][j]来表示MST中i到j的最大边权. 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 110; const int INF = 1e9; bool vis[maxn]; int d[maxn]; int pre[

POJ1679The Unique MST(次小生成树)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25203   Accepted: 8995 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire