POJ1679 Luogu4180 次小生成樹
The Unique MST Given a connected undirected graph, tell if its minimum spanning tree is unique.
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:
- V’ = V.
- 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 The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them. Output
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
struct data
{
int u,v,w;
bool vis;
} p[20010];
vector<int>G[110];
int per[110],maxd[110][110];
bool cmp(data a,data b)
{
return a.w < b.w;
}
int Union_Find(int x)
{
return x == per[x] ? x: per[x] = Union_Find(per[x]);
}
void kruskal()
{
sort(p,p+m,cmp);
for(int i=0; i<=n; i++)//初始化
{
G[i].clear();
G[i].push_back(i);
per[i]=i;
}
int sum=0,k=0;//sum是最小生成樹的值
for(int i=0; i<m; i++)
{
if(k==n-1) break;//n個點,最多n-1條邊
int x1=Union_Find(p[i].u),x2=Union_Find(p[i].v);
if(x1!=x2)
{
k++;
p[i].vis=1;//這條邊已經用過了
sum+=p[i].w;
int len_x1=G[x1].size();
int len_x2=G[x2].size();
for(int j=0; j<len_x1; j++)//更新兩點之間距離的最大值
for(int k=0; k<len_x2; k++)
maxd[G[x1][j]][G[x2][k]]=maxd[G[x2][k]][G[x1][j]]=p[i].w;
//因為後面的邊會越來越大,所以這裡可以直接等於當前邊的長度
per[x1]=x2;
int tem[110];
for(int j=0; j<len_x2; j++)//現在已經屬於一棵樹了,那麼我們就將點新增到相應的集合中
tem[j]=G[x2][j];
for(int j=0; j<len_x1; j++)
G[x2].push_back(G[x1][j]);
for(int j=0; j<len_x2; j++)
G[x1].push_back(tem[j]);
}
}
int cisum=INF;//次小生成樹的權值
for(int i=0; i<m; i++)
if(!p[i].vis)
cisum=min(cisum,sum+p[i].w-maxd[p[i].u][p[i].v]);
if(cisum>sum)
printf("%d\n",sum);
else
printf("Not Unique!\n");
}
int main()
{
int T;
scanf("%d\n",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w);
p[i].vis = false;
}
kruskal();
}
return 0;
}