只萌不新,求助次小生成树
查看原帖
只萌不新,求助次小生成树
328501
SSerWarriоrs_Cat楼主2020/7/22 16:59

RT

虽然在洛谷上过了这道题,但学校 OJ 上有一组 Hack 数据,且我挂了,求调错。

Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define int long long
inline 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 ^ 48); ch = getchar(); }
	return x * f;
}
const int N = 100010;
int n, m, tot, fa[N], sum, ans = 0x7fffffffffffffff;
struct S{ int LCA, MAX, CMAX; };
struct node{
	int u, v, w;
	bool operator < (const node&rhs)const{
		return w < rhs.w;
	}
}a[N * 3];
inline int anc(int x){
	return x == fa[x] ? x : fa[x] = anc(fa[x]);
}
struct edge{
	int v, w, nxt;
}e[N << 1];
int head[N << 1], cnt, dep[N], f[N][20], g[N][20][2];
bool vis[N * 3];
inline void add(int u, int v, int w){
	e[++cnt].v = v;
	e[cnt].w = w;
	e[cnt].nxt = head[u];
	head[u] = cnt;
}
inline void dfs(int u){
	for(int i = head[u]; i; i = e[i].nxt){
		int v = e[i].v, w = e[i].w;
		if(dep[v]) continue;
		dep[v] = dep[u] + 1;
		f[v][0] = u;
		g[v][0][0] = w;
		g[v][0][1] = -0x7f7f7f7f7f7f7f7f;
		for(int j = 1; j <= 17; ++j){
			f[v][j] = f[f[v][j - 1]][j - 1];
			if(g[v][j - 1][0] == g[f[v][j - 1]][j - 1][0]) g[v][j][1] = max(g[v][j - 1][1], g[f[v][j - 1]][j - 1][1]);
			if(g[v][j - 1][0] > g[f[v][j - 1]][j - 1][0]) g[v][j][1] = max(g[v][j - 1][1], g[f[v][j - 1]][j - 1][0]);
			if(g[v][j - 1][0] < g[f[v][j - 1]][j - 1][0]) g[v][j][1] = max(g[v][j - 1][0], g[f[v][j - 1]][j - 1][1]);
			g[v][j][0] = max(g[v][j - 1][0], g[f[v][j - 1]][j - 1][0]);
		}
		dfs(v);
	}
}
inline S lca(int a, int b){
	if(dep[a] < dep[b]) a ^= b ^= a ^= b;
	int ans1 = -0x7fffffffffffffff, ans2 = -0x7fffffffffffffff;
	for(int i = 17; i >= 0; --i) if(dep[f[a][i]] >= dep[b]){
		if(ans1 == g[a][i][0]) ans2 = max(ans2, g[a][i][1]);
		if(ans1 > g[a][i][0]) ans2 = max(ans2, g[a][i][0]);
		if(ans1 < g[a][i][0]) ans2 = max(ans1, g[a][i][1]);
		ans1 = max(ans1, g[a][i][0]);
		a = f[a][i];
	}
	if(a == b) return (S){a, ans1, ans2};
	for(int i = 17; i >= 0; --i) if(f[a][i] != f[b][i]){
		if(ans1 == g[a][i][0]) ans2 = max(ans2, g[a][i][1]);
		if(ans1 > g[a][i][0]) ans2 = max(ans2, g[a][i][0]);
		if(ans1 < g[a][i][0]) ans2 = max(ans1, g[a][i][1]);
		ans1 = max(ans1, g[a][i][0]);
		a = f[a][i];
		if(ans1 == g[b][i][0]) ans2 = max(ans2, g[b][i][1]);
		if(ans1 > g[b][i][0]) ans2 = max(ans2, g[b][i][0]);
		if(ans1 < g[b][i][0]) ans2 = max(ans1, g[b][i][1]);
		ans1 = max(ans1, g[b][i][0]);
		b = f[b][i];
	}
	if(ans1 == g[a][0][0]) ans2 = max(ans2, g[a][0][1]);
	if(ans1 > g[a][0][0]) ans2 = max(ans2, g[a][0][0]);
	if(ans1 < g[a][0][0]) ans2 = max(ans1, g[a][0][1]);
	ans1 = max(ans1, g[a][0][0]);
	return (S){f[a][0], ans1, ans2};
}
signed main(){
	n = read(); m = read();
	for(int i = 1; i <= m; ++i) a[i].u = read(), a[i].v = read(), a[i].w = read();
	for(int i = 1; i <= n; ++i) fa[i] = i;
	sort(a + 1, a + m + 1);
	for(int i = 1; i <= m; ++i){
		int u = a[i].u, v = a[i].v, w = a[i].w;
		if(anc(u) != anc(v)){
			vis[i] = 1;
			fa[fa[u]] = fa[v];
			add(u, v, w); add(v, u, w);
			sum += w; tot++;
			if(tot == n - 1) break;
		}
	}
	dfs(dep[1] = 1);
	for(int i = 1; i <= m; ++i){
		if(!vis[i]){
			int u = a[i].u, v = a[i].v, w = a[i].w;
			if(u == v) continue;
			S tmp = lca(u, v);
			int x = tmp.MAX, y = tmp.CMAX;
			if(x == w) ans = min(ans, sum - y + w);
			else ans = min(ans, sum - x + w);
		}
	}
	printf("%lld\n", ans);
	return 0;
}

做过的人应该都看得懂吧……

Input

Output

2020/7/22 16:59
加载中...