#蒟蒻复习之-----最小生成树#
//又一基础算法被深究QAQ
一般有两种方法,但考虑到博主只会kruskal,就不说Prim了
##kruskal##
kruskal是基于贪心的,对所有边sort,再从小加边
模板.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200000 + 100;
int n,m,f[maxn],tot,sum;
struct edge {
int u,v,w;
}e[maxn];
int read() {
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
bool cmp(edge a,edge b) {
return a.w < b.w;
}
int find(int x) {
if(f[x] == x) return f[x];
f[x] = find(f[x]);
return f[x];
}
int main() {
n = read(), m = read();
for(int i = 1; i <= m; i++) {
e[i].u = read(), e[i].v = read(), e[i].w = read();
}
for(int i = 1; i <= n; i++) f[i] = i;
sort(e+1,e+1+m,cmp);
for(int i = 1; i <= m; i++) {
int t1 = find(e[i].u), t2 = find(e[i].v);
if(t1 != t2) {
f[t1] = t2;
tot++;
sum += e[i].w;
}
if(tot == n-1) break;
}
cout<<sum<<endl;
return 0;
}
#次小生成树#
首先先要知道什么是最小瓶颈路
在无向图中求一条连接两点的路径, 使路径上权值最大的边尽可能的小, 则这条路径称为最小瓶颈路。
其实就是最小生成树
所以可以想到一种简单的方法,就是举要添加哪一条边, 加上这条边的权值, 然后将这条边连接的两点的最小瓶颈路上的最大边权减去, 就得到了一棵新的生成树。 复杂度O(n²+mlogm)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200000 + 100;
int n,m,f[maxn],tot,sum,vis[maxn];
struct node {
int u,v,w;
}no[maxn];
struct edge{
int u,v,w,next;
}e[maxn];
int head[maxn],cnt = 0;
void add(int u, int v, int w) {
e[++cnt] = (edge){u,v,w,head[u]};
head[u] = cnt;
}
int read() {
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
bool cmp(node a,node b) {
return a.w < b.w;
}
int find(int x) {
if(f[x] == x) return f[x];
f[x] = find(f[x]);
return f[x];
}
void kruskal() {
for(int i = 1; i <= n; i++) f[i] = i;
sort(no+1,no+1+m,cmp);
for(int i = 1; i <= m; i++) {
int t1 = find(no[i].u), t2 = find(no[i].v);
if(t1 != t2) {
f[t1] = t2;
tot++;
sum += no[i].w;
vis[i] = 1;
add(no[i].u,no[i].v,no[i].w);
add(no[i].v,no[i].u,no[i].w);
}
if(tot == n-1) break;
}
}
int now,d[600][600];
void dfs(int x, int fa, int num) {
d[now][x] = num;
for(int i = head[x]; i; i = e[i].next) {
int v = e[i].v;
if(v != fa) {
dfs(v,x,max(num,e[i].w));
}
}
}
void work() {
n = read(), m = read();
for(int i = 1; i <= m; i++) {
no[i].u = read(), no[i].v = read(), no[i].w = read();
}
kruskal();
cout<<"Cost: ";
if(tot != n-1) cout<<"-1"<<endl;
else cout<<sum<<endl;
for(int i = 1; i <= n; i++) {
now = i;
dfs(i,0,0);
}
int ans = 1<<29;
for(int i = 1;i <= m; i++) {
if(!vis[i]) ans = min(ans,sum + no[i].w - d[no[i].u][no[i].v]);
}
cout<<"Cost: ";
if(ans == 1<<29) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
int main() {
work();
return 0;
}