题意:给你一个有权值的无相图,判断最小生成树是否唯一。
求次小生成树,看是否和最小生成树权值一样 次小生成树模板
首先求出原图最小生成树,记录权值之和为MinST。枚举添加每条不在最小生成树上的边(u,v),加上以后一定会形成一个环。找到环上权值第二大的边(即除了(u,v)以外的权值最大的边),把它删掉,计算当前生成树的权值之和。取所有枚举修改的生成树权值之和的最小值,就是次小生成树。
链接:poj 1679
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 10001;
int n, m;
int num;
int p[maxn];
int maxx[101][101];
struct Edge //原始图
{
int from;
int to;
int w;
bool flag;
friend bool operator < (Edge x, Edge y) {
return x.w < y.w;
}
}e[maxn];
struct Tree //最小生成树
{
int to;
int w;
int next;
}tree[202];
int index[101];
struct Node //生成树的结点
{
int seq; //结点编号
int maxx; //从某个点到它的路径中的最大边的长度
};
void makeSet()
{
for(int i = 0; i <= n; i++)
{
p[i] = i;
}
}
int findSet(int x)
{
if(x != p[x])
p[x] = findSet(p[x]);
return p[x];
}
void addEdge(int from, int to, int w)
{
tree[num].to = to;
tree[num].w = w;
tree[num].next = index[from];
index[from] = num++;
}
int kruscal()
{
int x, y;
int edgeNum = 0;
int result = 0;
makeSet();
sort(e, e + m);
for(int i = 0; i < m; i++) {
x = findSet(e[i].from);
y = findSet(e[i].to);
if(x != y) {
edgeNum++;
addEdge(e[i].from,e[i].to,e[i].w);
addEdge(e[i].to,e[i].from,e[i].w);
e[i].flag = true;
p[x] = y;
result += e[i].w;
}
}
return edgeNum == n - 1 ? result : -1;
}
void bfs(int p)
{
bool used[101];
memset(used, 0, sizeof(used));
queue<Node> que;
Node now, adj;
now.maxx = 0;
now.seq = p;
que.push(now);
used[p] = true;
while(!que.empty()) {
Node q = que.front();
que.pop();
for(int i = index[q.seq]; i != -1; i = tree[i].next) {
adj.seq = tree[i].to;
adj.maxx = tree[i].w;
if(!used[adj.seq]) {
if(q.maxx > adj.maxx)
adj.maxx = q.maxx;
maxx[p][adj.seq] = adj.maxx;
used[adj.seq] = true;
que.push(adj);
}
}
}
}
void second_MST()
{
int mst = kruscal();
for(int i = 1; i <= n; i++)
bfs(i);
int smst = inf;
for(int i = 0; i < m; i++) {
if(!e[i].flag) {
if(mst + e[i].w - maxx[e[i].from][e[i].to] < smst)
smst = mst + e[i].w - maxx[e[i].from][e[i].to];
}
}
if(smst == mst)
printf("Not Unique!\n");
else
printf("%d\n", mst);
}
int main()
{
int cases;
int a, b, w;
scanf("%d", &cases);
while(cases--) {
scanf("%d %d", &n, &m);
for(int i = 0; i < m; i++) {
scanf("%d %d %d", &e[i].from, &e[i].to, &e[i].w);
e[i].flag = false;
}
num = 0;
memset(index, -1, sizeof(index));
second_MST();
}
return 0;
}