社区讨论

20分,倍增

P4180[BJWC2010] 严格次小生成树参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lo1i1sat
此快照首次捕获于
2023/10/22 21:23
2 年前
此快照最后确认于
2023/11/02 22:17
2 年前
查看原帖
CPP
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e5 + 10;
pair<int, pair<int, int> > line[N*6]; // 原图边
bool vis[N*6];
int bcj[N]; // 并查集fa 
int fa[N][25]; // 倍增跳父亲
int d[N][25][2]; // 维护路径上的最大值,和次大值 
int head[N];
int deep[N];
int tot;
int n, m;
int mst;
int mx = -1e9, cm = -1e9;
int ans = 1e9;

struct node {
	int to, next, dis;
}edge[N*2];

inline void add(int from, int to, int dis) {
	edge[++tot].to = to;
	edge[tot].dis = dis;
	edge[tot].next = head[from];
	head[from] = tot;
}

inline int read() {
	int x = 0;
	char ch = getchar();
	while ('0' > ch || ch > '9') ch = getchar();
	while ('0' <= ch && ch <= '9') x = x*10+ch-'0', ch = getchar();
	return x;
}

int find(int x) {
	if (bcj[x] == x) return x;
	return bcj[x] = find(bcj[x]);
}

void dfs(int x, int f) { // 初始化倍增 
	deep[x] = deep[f] + 1;
	for (int i=1; i<=20; i++) {
		d[x][i][0] = max(d[x][i-1][0], d[fa[x][i-1]][i-1][0]);
		if (d[x][i-1][0] < d[fa[x][i-1]][i-1][0]) {
//			cout << "updata:  ";
			d[x][i][1] = max(d[x][i-1][0], d[fa[x][i-1]][i-1][1]);
		}
		if (d[x][i-1][0] > d[fa[x][i-1]][i-1][0]) {
//			cout << "updata:  ";
			d[x][i][1] = max(d[x][i-1][1], d[fa[x][i-1]][i-1][0]);
		}
		if (d[x][i-1][0] == d[fa[x][i-1]][i-1][0]) {
//			cout << "updata:  ";
			d[x][i][1] = max(d[x][i-1][1], d[fa[x][i-1]][i-1][1]);
		}
//		cout << x << " " << i << " " << d[x][i][0] << " " << d[x][i][1] << endl;
	}
	for (int i=head[x]; i; i=edge[i].next) {
		int y = edge[i].to;
		int dis = edge[i].dis;
		if (y == f) continue;
//		cout << x << " " << y << " " << dis << endl;
		fa[y][0] = x;
		d[y][0][0] = dis;
		dfs(y, x);
	}
}

void updata(int x, int y) {
//	cout << x << "   -    " << y << endl;
	if (cm > mx) swap(cm, mx);
	if (x > cm) cm = x;
	if (cm > mx) swap(cm, mx);
	if (cm == mx) cm = -1e9; 
	if (cm > mx) swap(cm, mx);
	if (x > cm) cm = y;
	if (cm > mx) swap(cm, mx);
	if (cm == mx) cm = -1e9; 
}

void query(int x, int y) {
//	cout << x << " " << y << " ";
	mx = -1e9, cm = -1e9;
	if (deep[x] < deep[y]) swap(x, y);
	for (int i=20; i>=0; i--) {
		if (deep[fa[x][i]] >= deep[y]) {
			updata(d[x][i][0], d[x][i][1]);	
			x = fa[x][i];
		}
	}
//	cout << mx << " " << cm << endl;
	if (x == y) {
		return;
	}
	for (int i=20; i>=0; i--) {
		if (fa[x][i] != fa[y][i]) {
			updata(d[x][i][0], d[x][i][1]);
			updata(d[y][i][0], d[y][i][1]);
			x = fa[x][i];
			y = fa[y][i];
		}
	}
	updata(d[x][0][0], d[x][0][1]);
	updata(d[y][0][0], d[y][0][1]);
//	cout << mx << " " << cm << endl; 
} 


signed main() {
	memset(d, -0x3f, sizeof d);
	n = read();
	m = read();
	for (int i=1; i<=n; i++) {
		bcj[i] = i;
	}
	for (int i=1; i<=m; i++) {
		int x = read();
		int y = read();
		int z = read();
		line[i] = {z, {x, y}};
	}
	sort(line+1, line+m+1);
	for (int i=0, j=1; j<=m; j++) {
		int x = line[j].second.first;
		int y = line[j].second.second;
		int z = line[j].first;
		if (find(x) != find(y)) {
			mst += z;
			vis[j] = 1;
			bcj[find(x)] = find(y);
			add(x, y, z);
			add(y, x, z);
			if (++i == n) break;
		}
	}
	dfs(1, 0); 
	for (int j=1; j<=m; j++) {
		if (vis[j]) continue;
		int x = line[j].second.first;
		int y = line[j].second.second;
		int z = line[j].first;
		query(x, y);
//		cout << mx << " " << cm << " " << z << endl;
		if (mx != z) {
			ans = min(ans, mst-mx+z);
		} else if (cm != z) {
			ans = min(ans, mst-cm+z);
		}
	}
	printf("%lld", ans);
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...