其他分享
首页 > 其他分享> > 严格次小生成树 模板 P4180

严格次小生成树 模板 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