原来觉得是一个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. angular复选框式js树形菜单(二)

    删除(过滤)树形结构某一个子节点: function filterTreeData(treeData){ angular.forEach(treeData,function(item){ if (it ...

  2. hdu-1012-u Calculate e(水题)

    #include <iostream> using namespace std; int main() { ]; jiecheng[] = jiecheng[] = ; ; i<; ...

  3. Ubuntu16.04上安装搜狗输入法

    一.下载搜狗输入法的deb包: http://pinyin.sogou.com/linux/ 二.打开终端输入命令: $ sudo dpkg -i sogoupinyin_2.0.0.0078_i38 ...

  4. python 获取本机ip地址的方法(Unix 平台)

    #!/usr/bin/python import socket import fcntl import struct def get_ip_address(ifname): s = socket.so ...

  5. (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 上一节说到如 ...

  6. PHP怎么把经过UTF-8编码的中文字符转换成正常的中文

    问题的场景: html 为utf-8编码<meta http-equiv="Content-Type" content="text/html; charset=UT ...

  7. dwd面试记录与最近面试的一些感想。

    因为自己简历有些问题,额,面试官以为我有三年的工作经验. (吐槽一些智联的简历系统,)16年工作,一到18年自动变三年.这也忒坑人了. 工作年限一定要真实,避免出现问题,这会让面试官觉得你很不真诚. ...

  8. linux swap交换分区说明/管理

    https://coolnull.com/3699.html 一.SWAP说明1.1 SWAP概述当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释 ...

  9. 第三篇 ubuntu下,mysql 的root用户密码忘了怎么办?

    好长一段时间没有使用ubuntu了,今天进来玩玩,结果连mysql的root用户密码都忘记了.就上网找了一下,发现如下解决办法,试了一下,可行!记录在此,环境问题,是需要注意的. Ubuntu Ser ...

  10. IDEA运行Java的项目出现页面空白

    问题效果: 解决方案: 在发布的时候不应该把Tomcat的jar打包入内.