社区讨论
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 条回复,欢迎继续交流。
正在加载回复...