严格次小生成树 模板 P4180
作者:互联网
注意严格次小这个细节问题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
const int M = 3e5 + 10;
int n,m,head[N],tot,nxt[M],to[M],f[N];
ll w[M];
struct node {
int u,v;
ll ew;
bool tag;
bool operator < (const node& e) const {
return ew < e.ew;
}
}edge[M];
void add(int u,int v,ll z) {
to[++tot] = v,w[tot] = z,nxt[tot] = head[u],head[u] = tot;
}
int find(int x) {
return f[x] == x ? x : f[x] = find(f[x]);
}
ll kruskal() {
for(int i = 1;i <= n;i ++) f[i] = i;
int used = 0;
ll s = 0;
sort(edge + 1,edge + 1 + m);
for(int i = 1;i <= m;i ++) {
int fu = find(edge[i].u),fv = find(edge[i].v);
if(fu != fv) {
f[fv] = fu;
used ++;
edge[i].tag = true;
s += edge[i].ew;
add(edge[i].u,edge[i].v,edge[i].ew);
add(edge[i].v,edge[i].u,edge[i].ew);
}
if(used == n - 1) break;
}
return s;
}
int fa[N][20],dep[N];
ll v1[N][20],v2[N][20];
void dfs(int u,int pa,int x) {
dep[u] = x;
for(int i = head[u];i;i = nxt[i]) {
int v = to[i];
if(v == pa) continue;
fa[v][0] = u;
v1[v][0] = w[i];
for(int i = 1;i < 20;i ++) {
fa[v][i] = fa[fa[v][i - 1]][i - 1];
int pref = fa[v][i - 1];
v1[v][i] = max(v1[v][i - 1],v1[pref][i - 1]);
v2[v][i] = max(v2[v][i - 1],v2[pref][i - 1]);
if(v1[v][i - 1] > v1[pref][i - 1])
v2[v][i] = max(v2[v][i],v1[pref][i - 1]);
else if(v1[v][i - 1] < v1[pref][i - 1])
v2[v][i] = max(v2[v][i],v1[v][i - 1]);
}
dfs(v,u,x + 1);
}
}
int LCA(int x,int y) {
if(dep[x] < dep[y]) swap(x,y);
for(int i = 19;i >= 0;i --) {
if(dep[fa[x][i]] >= dep[y]) {
x = fa[x][i];
}
}
if(x == y) return x;
for(int i = 19;i >= 0;i --) {
if(fa[x][i] != fa[y][i]) {
x = fa[x][i],y = fa[y][i];
}
}
return fa[x][0];
}
ll calc(int u,int lca,ll z) {
ll res = 0;
for(int i = 19;i >= 0;i --) {
if(dep[fa[u][i]] >= dep[lca]) {
if(z == v1[u][i]) {
res = max(res,v2[u][i]);
} else {
res = max(res,v1[u][i]);
}
u = fa[u][i];
}
}
return res;
}
int main() {
cin >> n >> m;
for(int i = 1;i <= m;i ++) {
int x,y;ll z; cin >> x >> y >> z;
edge[i].u = x,edge[i].v = y,edge[i].ew = z,edge[i].tag = false;
}
ll s = kruskal(),ans = 1e18;
dfs(1,0,1);
for(int i = 1;i <= m;i ++) {
if(edge[i].tag || edge[i].u == edge[i].v) continue;//注意自环直接判掉 不合法
int lca = LCA(edge[i].u,edge[i].v);
ll del = max(calc(edge[i].u,lca,edge[i].ew),calc(edge[i].v,lca,edge[i].ew));
ans = min(ans,s + edge[i].ew - del);
}
cout << ans << '\n';
return 0;
}
标签:dep,v1,int,res,ll,生成,fa,P4180,模板 来源: https://www.cnblogs.com/forward77/p/16285166.html