判断最小生成树的唯一性

来源:互联网 发布:做报表的软件 编辑:程序博客网 时间:2024/06/06 12:27

先用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;}


0 0
原创粉丝点击