CF609E Minimum spanning tree for each edge
原来觉得是一个LCT,感觉自己瞬间傻掉……
考虑到先做一个最小生成树求出做最小生成树的代价$ans$,顺便标记一下树边和非树边,把边按照输入$id$排序回去之后扫,如果扫到一条树边,那么此时的答案就是$ans$,如果扫到一条非树边,那么相当于一条边强制连上之后再切去环里的一条边使这个基环树重新变成一棵树,那么贪心一下,肯定要切掉最大的边,而这个断开一个口的环其实就是树上的一条路径,这个过程只要倍增就可以维护。
时间复杂度$O(nlogn)$。
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = 2e5 + ;
const int Lg = ; int n, m, dep[N], fa[N][Lg], tot = , head[N], ufs[N];
ll ans = 0LL, maxn[N][Lg]; struct Edge {
int to, nxt;
ll val;
} e[N << ]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} struct Pathway {
int u, v, id;
ll val;
bool inTree;
} path[N]; bool cmpv(const Pathway &x, const Pathway &y) {
return x.val < y.val;
} bool cmpi(const Pathway &x, const Pathway &y) {
return x.id < y.id;
} template <typename T>
inline void read(T &X) {
X = ;
char ch = ;
T op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline ll max(ll x, ll y) {
return x > y ? x : y;
} inline void chkMax(ll &x, ll y) {
if(y > x) x = y;
} inline void init() {
for(int i = ; i <= n; i++) ufs[i] = i;
} int find(int x) {
return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
} inline void kruskal() {
init();
sort(path + , path + + m, cmpv);
for(int cnt = , i = ; i <= m; i++) {
int u = find(path[i].u), v = find(path[i].v);
if(u == v) continue;
cnt++, ufs[u] = v, path[i].inTree = , ans += path[i].val;
add(path[i].u, path[i].v, path[i].val), add(path[i].v, path[i].u, path[i].val);
if(cnt >= n - ) break;
}
} void dfs(int x, int fat, int depth, ll nowDis) {
fa[x][] = fat, dep[x] = depth, maxn[x][] = nowDis;
for(int i = ; i <= ; i++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
maxn[x][i] = max(maxn[fa[x][i - ]][i - ], maxn[x][i - ]);
}
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs(y, x, depth + , e[i].val);
}
} inline void swap(int &x, int &y) {
int t = x;
x = y;
y = t;
} inline ll getMax(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
ll res = 0LL;
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y])
chkMax(res, maxn[x][i]), x = fa[x][i];
if(x == y) return res;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i]) {
chkMax(res, maxn[x][i]);
chkMax(res, maxn[y][i]);
x = fa[x][i], y = fa[y][i];
}
return max(res, max(maxn[x][], maxn[y][]));
} inline void solve() {
sort(path + , path + + m, cmpi); /* for(int i = 1; i <= m; i++)
printf("%d %d %lld %d\n", path[i].u, path[i].v, path[i].val, path[i].inTree);
printf("\n%lld\n", ans); */ for(int i = ; i <= m; i++) {
if(path[i].inTree) printf("%lld\n", ans);
else printf("%lld\n", ans - getMax(path[i].u, path[i].v) + path[i].val);
}
} int main() {
read(n), read(m);
for(int i = ; i <= m; i++) {
read(path[i].u), read(path[i].v), read(path[i].val);
path[i].id = i, path[i].inTree = ;
} kruskal();
dfs(, , , 0LL);
solve(); return ;
}
CF609E Minimum spanning tree for each edge的更多相关文章
- cf609E Minimum Spanning Tree For Each Edge (kruskal+倍增Lca)
先kruskal求出一个最小生成树,然后对于每条非树边(a,b),从树上找a到b路径上最大的边,来把它替换掉,就是包含这条边的最小生成树 #include<bits/stdc++.h> # ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST
E. Minimum spanning tree for each edge Connected undirected weighted graph without self-loops and ...
- CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
- Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA链上最大值
E. Minimum spanning tree for each edge 题目连接: http://www.codeforces.com/contest/609/problem/E Descrip ...
- [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]
这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
- codeforces 609E Minimum spanning tree for each edge
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
- Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge 树上倍增
E. Minimum spanning tree for each edge 题目连接: http://www.codeforces.com/contest/609/problem/E Descrip ...
- Codeforces Edu3 E. Minimum spanning tree for each edge
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
随机推荐
- 【pandas】pandas.DataFrame.rename()---重置索引名称
官方文档 github地址 例子: 创建DataFrame ### 导入模块 import numpy as np import pandas as pd import matplotlib.pypl ...
- Arc066_F Contest with Drinks Hard
传送门 题目大意 有一个长为$N$的序列$A$,你要构造一个长为$N$的$01$序列使得$01$序列全部由$1$组成的子串个数$-$两个序列的对应位置两两乘积之和最大,每次独立的询问给定$pos,x$ ...
- UVA - 1608 Non-boring sequences (分治,中途相遇法)
如果一个序列中是否存在一段连续子序列中的每个元素在该子序列中都出现了至少两次,那么这个序列是无聊的,反正则不无聊.给你一个长度为n(n<=200000)的序列,判断这个序列是否无聊. 稀里糊涂A ...
- 《Orange’s 一个操作系统的实现》1.搭建操作系统开发环境
书中给出了两种环境:windows和linux,平台选择根据自己喜好.本人这里选择ubuntu10.04+virtualbox作为开发平台. 1.下载.安装VirtualBox http:// ...
- angular 的杂碎报错小知识
1:[ng:areq] Angular出现这种错误的原因,是由于没有在页面中使用模块引入controller导致的 所以 请确保你定义了这个controller后也引用了它. 2:Failed to ...
- CF 622F The Sum of the k-th Powers——拉格朗日插值
题目:http://codeforces.com/problemset/problem/622/F 发现 sigma(i=1~n) i 是一个二次的多项式( (1+n)*n/2 ),sigma(i=1 ...
- 2.Linux下安装Jenkins
1.安装jenkins的前提是安装好jdk环境,自行安装jdk,若安装成功后,使用一下命令即可成功安装jenkins: wget -O /etc/yum.repos.d/jenkins.repo ht ...
- POJ3321(dfs序列+树状数组)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25711 Accepted: 7624 Descr ...
- Disconf web管理端安装
1.环境配置配置java.maven环境,并安装mysql,reids,zookeeeper,Nginx2.下载disconf下载https://codeload.github.com/knightl ...
- MySQL脚本自动安装mysql-5.6.15-linux-glibc2.5-x86_64.tar.gz
脚本安装mysql-5.6.15-linux-glibc2.5-x86_64.tar.gz 先准备好数据文件的路径 softdir='/data/soft' 把脚本和tar包放在相应的路径下,其实就是 ...