1. 程式人生 > >判斷最小生成樹的唯一性

判斷最小生成樹的唯一性

先用kruskal演算法算出最小生成樹,並把最小生成樹的邊記錄下來。然後依次列舉刪除邊,用其他的邊再次使用kruskal演算法算出最小生成樹。如果算出的代價和原來的相同,則不唯一,否則唯一。另外當我們刪除一條邊之後,可能根本構不成一顆生成樹,要判斷一下。

程式碼如下:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <queue>
#include <new>
#include <set>
#include <map>

using namespace std;

const int maxn = 1000;
int p[maxn], x[maxn], y[maxn], n;
struct edge
{
    int u, v, cost;
    bool operator < (const edge& b) const
    {
        return cost < b.cost;
    }
};
vector<edge> edges;
vector<int> mst_edges;

int find_root(int x)
{
    if (p[x] == -1) return x;
    return p[x] = find_root(p[x]);
}

void kruskal()
{
    memset(p, -1, sizeof(p));
    sort(edges.begin(), edges.end());

    mst_edges.clear();
    int cost = 0;
    for (int i = 0; i < edges.size(); i++)
    {
        int x = edges[i].u, y = edges[i].v;
        int rx = find_root(x);
        int ry = find_root(y);
        if (rx != ry)
        {
            p[rx] = ry;
            cost += edges[i].cost;
            mst_edges.push_back(i);
        }
    }

    printf("%d\n", cost);

    bool ok = false;
    for (int i = 0; i < mst_edges.size(); i++)
    {
        memset(p, -1, sizeof(p));
        int ans = 0, k = 0;
        for (int j = 0; j < edges.size(); j++)
        {
            if (mst_edges[i] == j) continue;
            int x = edges[j].u, y = edges[j].v;
            int rx = find_root(x);
            int ry = find_root(y);
            if (rx != ry)
            {
                p[rx] = ry;
                ans += edges[j].cost;
                k++;
            }
        }

        if (ans == cost && k == n - 1)//新算出的生成樹的代價和最小生成樹代價相同,且能構成一棵樹(最小生成樹的邊數肯定是n - 1)
        {
            ok = true;
            break;
        }
    }

    if (ok) printf("Yes\n");
    else printf("No\n");
}

int main()
{
    //freopen("1.txt", "r", stdin);
    int T, Case = 0;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d", &n);
        edges.clear();
        for (int i = 1; i <= n; i++) scanf("%d%d", &x[i], &y[i]);
        for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++)
        {
            int d = abs(x[i] - x[j]) + abs(y[i] - y[j]);
            edges.push_back(edge{i, j, d});
        }

        printf("case #%d:\n", Case++);

        kruskal();
    }
    return 0;
}


相關推薦

POJ-1679 The Unique MST (判斷小生成樹唯一性)

href target tin cout strong using \n ren string <題目鏈接> 題目大意: 給定一張無向圖,判斷其最小生成樹是否唯一。 解題分析: 對圖中每條邊,掃描其它邊,如果存在相同權值的邊,則標記該邊;用kruskal求出MS

判斷小生成樹唯一性

先用kruskal演算法算出最小生成樹,並把最小生成樹的邊記錄下來。然後依次列舉刪除邊,用其他的邊再次使用kruskal演算法算出最小生成樹。如果算出的代價和原來的相同,則不唯一,否則唯一。另外當我們刪除一條邊之後,可能根本構不成一顆生成樹,要判斷一下。 程式碼如下: #

POJ 1679 The Unique MST(判斷小生成樹是否唯一)

connect col pro case pac str other sid 一次 題目鏈接: http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if it

判斷小生成樹是否唯一

在最小生成樹的推論中,生成樹一定包含連線兩個森林中間權值最小的邊,所以在做最小生成樹的同時統計這些備選邊,若備選邊大於所需的,則不唯一。 #include<bits/stdc++.h> #define f(i,l,r) for(i=(l);i<=(r);i++) using

資料結構與演算法之------判斷小生成樹是否唯一

判斷最小生成樹是否唯一 原文連結:http://www.cnblogs.com/wkfvawl/p/9845689.html 我們知道在構造最小生成樹的時候有可能會選擇不同的邊,這樣構造的最小生成樹不相同,但是最小生成樹的權是唯一的! 毫無疑問,無向圖中存在相同權值的邊是最小生成樹不唯一

判斷小生成樹是否為一(krustra)

具體思路: 首先跑一遍最短路演算法,然後將使用到的邊標記一下,同時使用一個數組記錄每一個權值出現的次數,如果出現過的權值超過一次,那麼每一次標記一條標記過的邊,再去跑最短路演算法,如果去除這條邊之後的權值和未未去除的時候的權值相同,那麼這個最短生成樹就不是唯一的,否則就

poj 1679()判斷小生成樹是否唯一、次小生成樹模板)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K

poj 1679 The Unique MST (判斷小生成樹是否唯一)

題意:判斷最小生成樹是否唯一, 若唯一,輸出最小權值和,否則,輸出  Not Unique! 判斷最小生成樹是否唯一的思路: 1、對圖中的每一條邊,掃描其他邊,如果存在相同權值的邊,則對該邊做標

POJ 1679 The Unique MST (prim判斷小生成樹是否唯一)

思路: 在prim演算法中,假設有a,b,c三個點。當更新加入c點時,若ac和bc的權值都為最小值,說明最小生成樹不唯一。 理由很簡單,當存在兩個最小權值時,abc和acb都是最小生成樹。 #incl

Networking POJ1287 小生成樹Prim(注意判斷重邊)

http://poj.org/problem?id=1287 #include<iostream> #include<math.h> #include<stdio.h> #include<string.h> #include<math.h&g

Networking POJ1287 小生成樹 Kruscal (根據Kruscal特點,不用判斷重邊)

http://poj.org/problem?id=1287 給定點以及邊,這裡需要注意的是50個點最多,那麼邊最多有50*49條,注意陣列不要太小了。 Kruscal模板題 #include<iostream> #include<math.h> #include

7-14 小生成樹唯一性(30 分) 生成樹綜合練習題

題目描述: 7-14 最小生成樹的唯一性(30 分) 給定一個帶權無向圖,如果是連通圖,則至少存在一棵最小生成樹,有時最小生成樹並不唯一。本題就要求你計算最小生成樹的總權重,並且判斷其是否唯一。 輸入格式: 首先第一行給出兩個整數:無向

並查集-用並查集判斷圖中是否有環(能夠應用到kruskal的小生成樹

     先不介紹並查集的概念,先從它的應用說起吧,它有兩個功能,第一就是判斷給定的一個節點是否屬於某一個集合,更確切的說是屬於哪個集合。第二個功能就是合併兩個集合。       給定一組資料,如:1, 2, 3, 4, 5, 6, 7, 8,  9,他們是一個大的集合,但

判斷唯一小生成樹(次小生成樹

先說一下最小生成樹的思路 將邊按長度從小到大排序 依次判斷 如果會出現環就跳過這條邊(用到並查集) 否則新增 直到新增到n-1條邊 就是最小生成樹 至於次小生成樹 先提供第一種思路 先建成最小生成樹 顯然繼續再新增任意一條邊都會形成環 倘若新添的這條邊與形成的環中除新添的邊

The Unique MST——判斷一個連通無向圖的小生成樹是否是唯一的

Think: 1知識點:判斷一個連通無向圖的最小生成樹是否是唯一的+最小生成樹_Prim演算法+記錄路徑 2題意:給定一個連通無向圖,判斷這個連通無向圖的最小生成樹是否是唯一的 3錯誤反思: 4思路: 1>思路1:第一遍Prim演算法求出路徑最小

7-14 小生成樹唯一性

給定一個帶權無向圖,如果是連通圖,則至少存在一棵最小生成樹,有時最小生成樹並不唯一。本題就要求你計算最小生成樹的總權重,並且判斷其是否唯一。輸入格式:首先第一行給出兩個整數:無向圖中頂點數 N(≤)和邊數 M。隨後 M 行,每行給出一條邊的兩個端點和權重,格式為“頂點1 頂點

The Unique MST 1679(小生成樹的不唯一性

The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24076 Accepted: 8551 Description Given a connected undirect

HDU 4786(小生成樹 kruskal)

desc cpp using tran soft fine put sea can 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4786 Problem Description   Coach Pang is

【BZOJ3714】[PA2014]Kuglarz 小生成樹

include 是我 light ace 編號 兩個 -i ring 奇偶性 【BZOJ3714】[PA2014]Kuglarz Description 魔術師的桌子上有n個杯子排成一行,編號為1,2,…,n,其中某些杯子底下藏有一個小球,如果你準確地

poj1861 小生成樹 prim &amp; kruskal

模板 bool content bre 水題 esp algorithm puts class // poj1861 最小生成樹 prim & kruskal // // 一個水題,為的僅僅是回味一下模板。日後好有個照顧不是 #include