链接:
http://poj.org/problem?id=1679
题目:
Description
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 following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
Output
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
Source
题目大意:
问一个图的最小生成树是否是唯一存在的。
分析与总结:
一个图的最小生成树是否是唯一的,那么只需要看它的次小生成树是否和最小生成树相等,是的话就说明不是唯一的。
所以这题的关键在于求最小生成树。
在最先生成树的基础上, 添加一条不属于构成最小成树的边,那么就有了共n条边,显然会形成一个回环,所以,需要除去这个回环中的最大那条边(不包括添加的这条),那么就会形成一个新的生成树。 依次枚举添加每一条,结果最小的那个就是次小生成树。
在用prim求最小生成树时,用一个二位数组path【a】【b】, 来存a到b的最长一条边。
之前自己整了个Prim的模板,做这题只稍微改了下模板。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int VN = 105; //尺寸
const int INF = 2000000000;
template<typename Type>
class Prim{
public:
inline void init(int _n){
n=_n; MSTsum = 0;
for(int i=0; i<=n; ++i){
w[i][i] = INF;
for(int j=i+1; j<=n; ++j)
w[i][j]=w[j][i]=INF;
}
}
inline void insert(int u, int v, Type weight){
if(w[u][v]>weight) w[u][v] = weight; //注意可能有重复边
}
Type prim(){
memset(vis, 0, sizeof(vis));
memset(path, 0, sizeof(path));
memset(used, 0, sizeof(used));
vis[1] = true;
for(int i=1; i<=n; ++i){
key[i] = w[1][i]; pre[i] = 1;
}
for(int i=1; i<n; ++i){
int u=-1;
for(int j=1; j<=n; ++j)if(!vis[j]){
if(u==-1||key[j]<key[u]) u=j;
}
if(w[pre[u]][u]==INF) return -1;
used[pre[u]][u] = used[u][pre[u]] = true;
MSTsum += w[pre[u]][u];
vis[u] = true;
for(int j=1; j<=n; ++j){
if(vis[j]&&j!=u){
path[u][j]=path[j][u]=max(path[j][pre[u]],key[u]);
}
if(!vis[j]&&key[j]>w[u][j]){
key[j] = w[u][j]; pre[j] = u;
}
}
}
return MSTsum;
}
int is_unique(){
prim();
int tmp;
for(int i=1; i<=n; ++i){
for(int j=i+1; j<=n; ++j)if(!used[i][j]){
tmp = MSTsum + path[i][j] - w[i][j];
if(tmp==MSTsum) return -1;
}
}
return MSTsum;
}
private:
Type MSTsum;
Type w[VN][VN], key[VN];
int pre[VN], path[VN][VN], n;
bool vis[VN], used[VN][VN];
};
Prim<int>G;
int main(){
int T, n, m, a, b, c;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
G.init(n);
for(int i=0; i<m; ++i){
scanf("%d%d%d",&a,&b,&c);
G.insert(a,b,c);
G.insert(b,a,c);
}
int ans = G.is_unique();
if(ans==-1) puts("Not Unique!");
else printf("%d\n", ans);
}
return 0;
}
—— 生命的意义,在于赋予它意义。
原创 http://blog.youkuaiyun.com/shuangde800 , By D_Double (转载请标明)