POJ1679The Unique MST (Secondly Small Spanning Tree)

topic

The idea of ​​this question is to judge whether the weights of the minimum spanning tree and the second-smallest spanning tree of a graph are the same, that is, whether the minimum spanning tree is unique. First run prim to find the minimum spanning tree, then add each edge that is not in the minimum spanning tree to the MST, then delete the edge with the largest weight on the formed ring, and finally judge it.

Senior qq's blog: https://blog.csdn.net/qq_28954601/article/details/71102139

Other big guys: https://www.cnblogs.com/bianjunting/p/10829212.html

My code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e2 + 10;
const int maxm = 1e5 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 11092019;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
int n, m, e[maxn][maxn];
int Max[maxn][maxn]; // 区间内权值最大的边权
int lowc[maxn]; // 生成树到每个点的最短距离
int pre[maxn]; // 该点是由哪个店 "扩展" 进入 MST 的
bool used[maxn][maxn]; // 当前边有没有被使用过
bool vis[maxn];      // prim 算法 标记已经加入 MST 的点
void init(int n)
{
    memset(e, inf, sizeof e);
    for (int i = 1; i <= n; i++)
        e[i][i] = 0;
}
int prim(int n)
{
    int ans = 0;
    memset(vis, false, sizeof vis);
    memset(used, false, sizeof used);
    memset(Max, 0, sizeof Max);
    vis[1] = true;
    pre[1] = -1; // 1 没有任何点引入
    lowc[1] = 0;
    for (int i = 2; i <= n; i++)
        lowc[i] = e[1][i], pre[i] = 1;// 一开始每个点都是由 1 号点引入的
    for (int i = 1; i < n; i++)
    {
        int minc = inf;
        int p;
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && lowc[j] < minc)
            {
                p = j;
                minc = lowc[j];
            }
        }
        ans += minc;
        vis[p] = true;
        used[p][pre[p]] = used[pre[p]][p] = true;
        for (int j = 1; j <= n; j++)
        {
            if (vis[j] && j != p) // 对于已经在 MST 里面的点
            {
                Max[j][p] = Max[p][j] = max(Max[j][pre[p]], lowc[p]); // 更新 i->j 上的最大权值 
            }
            if (!vis[j] && lowc[j] > e[p][j])// 更新 MST 到各点的距离
            {
                pre[j] = p;
                lowc[j] = e[p][j];
            }
        }
    }
    return ans;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    IO;
    int T, a, b, c;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d %d", &n, &m);
        init(n);
        for (int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &a, &b, &c);
            e[a][b] = e[b][a] = c;
        }
        int ans = prim(n);
        int temp = inf;
        for (int i = 1; i <= n; i++)
            for (int j = i + 1; j <= n; j++)
                if (e[i][j] != inf && !used[i][j]) // 用每个不在 MST 更新temp
                    temp = min(temp, ans + e[i][j] - Max[i][j]);
        if (temp == ans)
            printf("Not Unique!\n");
        else
            printf("%d\n", ans);
    }
    return 0;
}

 

 

Guess you like

Origin blog.csdn.net/qq_44115065/article/details/106126595