POJ 1679 最小生成树是否唯一 次小生成树

来源:互联网 发布:淘宝如何好评截图 编辑:程序博客网 时间:2024/05/29 10:47

题意:

给你一个图,问你最小生成树是否唯一?

思路:

其实就是求次小生成树,如果最小生成树和次小生成树的花费一样那么,最小生成树就不是唯一的。

这题用了一些技巧,稍稍修改了kruscal算法,对于每条边,如果有一条和它花费相同的边存在,那么就删去它同时求最小生成树,并进行判断

<pre name="code" class="cpp">#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cstring>#define MAX_E 5000using namespace std;bool first;int par[MAX_E];int ranks[MAX_E];struct edge{int u, v;int cost;bool equ;//记录是否存在和这条边花费相等的边bool del;//这条边是否被删除bool used;//这条边是否在最小生成树中被使用};edge es[MAX_E];int V, E;void init(int n){for (int i = 1; i <= n; i++)//注意初始化范围{par[i] = i;ranks[i] = 0;}}int find(int x){if (par[x] == x){return x;}else{return par[x] = find(par[x]);}}void unite(int x, int y){x = find(x);y = find(y);if (x == y)  return;if (ranks[x] < ranks[y]){par[x] = y;}else{par[y] = x;if (ranks[x] == ranks[y]) ranks[x] ++;}}bool same(int x, int y){return find(x) == find(y);}bool comp(const edge &e1, const edge &e2){return e1.cost < e2.cost;}int kruskal(){sort(es, es + E, comp);init(V);int res = 0;for (int i = 0; i < E; i++){edge e = es[i];if ((!same(e.v, e.u)) && (!e.del))//注意判断这条边是否被删除{unite(e.u, e.v);if(first)es[i].used = 1;//在第一次求最小生成树的时候记录这条边被使用了res += e.cost;}}return res;}int main(){int T;cin >> T;while (T--){cin >> V >> E;for (int i = 0; i < E; i++){int u, v, w;scanf("%d %d %d", &u, &v, &w);es[i].u = u;es[i].v = v;es[i].cost = w;es[i].del = 0;es[i].equ = 0;es[i].used = 0;}first = true;//表示是否是第一次求最小生成树int res1 = kruskal();first = false;int i;for (int i = 0; i < E; i++) {for (int j = 0; j < E; j++) {if (i == j)continue;if (es[i].cost == es[j].cost) {es[i].equ = 1;}}}for (i = 0; i < E; ++i){if (es[i].used && es[i].equ){es[i].del = 1;//如果存在花费相等的边就删去这条边并求最小生成树int res2 = kruskal();if (res1 == res2){printf("Not Unique!\n");break;}es[i].del = 0;}}if (i >= E) printf("%d\n", res1);}return 0;}


                                             
0 0