原来觉得是一个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的更多相关文章

  1. cf609E Minimum Spanning Tree For Each Edge (kruskal+倍增Lca)

    先kruskal求出一个最小生成树,然后对于每条非树边(a,b),从树上找a到b路径上最大的边,来把它替换掉,就是包含这条边的最小生成树 #include<bits/stdc++.h> # ...

  2. 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 ...

  3. 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 ...

  4. 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 ...

  5. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

  6. 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 ...

  7. 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 ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. winform使用相对路径读取文件的方法

    获取exe文件的路径进行截取,分两次进行,然后拼接文件名,形成全路径 代码如下: string haarXmlPath = @"haarcascade_frontalface_alt_tre ...

  2. dilworth定理的通俗讲解

    度娘定义:在数学理论中的序理论与组合数学中,Dilworth定理根据序列划分的最小数量的链描述了任何有限偏序集的宽度.其名称取自数学家Robert P. Dilworth. 反链是一种偏序集,其任意两 ...

  3. uva120 Stacks of Flapjacks (构造法)

    这个题没什么算法,就是想出怎么把答案构造出来就行. 思路:越大的越放在底端,那么每次就找出还没搞定的最大的,把它移到当前还没定好的那些位置的最底端,定好的就不用管了. 这道题要处理好输入,每次输入的一 ...

  4. H5实现登录

    1.主要就是获取cookie并每次发送请求时都带着:登录请求 2.添加HTTP Cookie管理器 3.登录请求时,加正则表达式提取器 取出返回的cookie ①使用charles抓包查看cookie ...

  5. 数据清洗记录,pandas

    pandas数据清洗:http://www.it165.net/pro/html/201405/14269.html data=pd.Series([1,2,3,4]) data.replace([1 ...

  6. ipad与iphone的屏幕分辨率

    1.ipad分辨率,iphone 6 iPhone设备      尺寸 分辨率                   点iPhone 3和3s  3.5英寸    (320×480)         3 ...

  7. Java实现Bag类

    Java实现Bag类 import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Scan ...

  8. SqlServer 用户和权限操作

    use [master] GO --创建用户,Test,密码Test CREATE LOGIN [TestUser] WITH PASSWORD=N'Test', DEFAULT_DATABASE=[ ...

  9. MockMVC

    随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架 Spring MVC测试框架提 ...

  10. 映射块设备提示rbd: sysfs write failed的解决方法

    标签(空格分隔): ceph ceph运维 rbd 问题描述: 创建完镜像foo后,映射镜像时提示下面的错误: [root@node3 ~]# rbd map testpool/foo rbd: sy ...