题目大意:求最小生成树的值是否唯一,唯一输出这个值,不唯一则输出Not Unique!
解题思路:先求出最小生成树,保存最小生成树的路径,然后按边的大小由小到大枚举每条没有加入最小生成树的边比如是(u,v),在已经形成的最小生成树种,取u到v路径上最大的边的权值,比较(u,v)的这个最大权值的大小,如果相等,说明最小生成树不唯一,如果不相等,说明唯一。
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
#define MAX_N 101
struct edge
{
int u, v;
int weight;
inline bool operator < (const edge & b) const
{
return weight > b.weight;
}
};
struct node
{
int v;
int w;
};
priority_queue<edge> heap;
priority_queue<edge> saveheap;
int pre[MAX_N], parent[MAX_N], value[MAX_N], total, m, n;
bool visited[MAX_N];
void Krukstral();
int FindSet(int a);
bool UnionSet(int a, int b);
bool solve();
int main()
{
int t;
scanf("%d",&t);
while((t--) != 0)
{
while(!heap.empty())
heap.pop();
while(!saveheap.empty())
saveheap.pop();
total = 0;
memset(value, -1, sizeof(value));
memset(pre, -1, sizeof(pre));
memset(parent, -1, sizeof(parent));
scanf("%d %d", &n, &m);
for(int i = 0; i < n; i++)
{
pre[i] = i;
}
for(int i = 0; i < m; i++)
{
int xi, yi, wi;
scanf("%d %d %d", &xi, &yi, &wi);
xi--; yi--;
if(xi > yi)
{
xi ^= yi;
yi ^= xi;
xi ^= yi;
}
edge te;
te.u = xi;
te.v = yi;
te.weight = wi;
heap.push(te);
}
Krukstral();
if(!solve())
printf("Not Unique!\n");
else
printf("%d\n", total);
}
return 0;
}
void Krukstral()
{
int num = 0;
while(!heap.empty())
{
edge te = heap.top();
heap.pop();
if(!UnionSet(te.u, te.v))
{
num++;
parent[te.v] = te.u;
value[te.v] = te.weight;
total += te.weight;
}
else
saveheap.push(te);
if(num == n - 1)
break;
}
}
int FindSet(int a)
{
if(pre[a] != a)
pre[a] = FindSet(pre[a]);
return pre[a];
}
bool UnionSet(int a, int b)
{
int x, y;
bool flag = true;
x = FindSet(a);
y = FindSet(b);
if(x != y)
{
pre[y] = x;
flag = false;
}
return flag;
}
bool solve()
{
edge te;
while(!saveheap.empty()) //处理那些之前加入最小生成树时属于同一个集合不能加入的边
{
te = saveheap.top();
saveheap.pop();
int maxVal = -1;
int end = te.v;
//找出u到v最小生成树中路径的最大值。
while(end != te.u && end != -1)
{
if(maxVal < value[end])
maxVal = value[end];
end = parent[end];
}
if(end != te.u)
{
end = te.u;
while(end != te.v && end != -1)
{
if(maxVal < value[end])
maxVal = value[end];
end = parent[end];
}
}
if(maxVal >= te.weight)
return false;
}
while(!heap.empty()) //处理剩下的没加入的边
{
te = heap.top();
heap.pop();
int maxVal = -1;
int end = te.v;
while(end != te.u && end != -1)
{
if(maxVal < value[end])
maxVal = value[end];
end = parent[end];
}
if(end != te.u)
{
end = te.u;
while(end != te.v && end != -1)
{
if(maxVal < value[end])
maxVal = value[end];
end = parent[end];
}
}
if(maxVal >= te.weight)
return false;
}
return true;
}