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 ...
随机推荐
- Git学习--版本回退
现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下: Git is a distributed version control system. ...
- Eclipse中Maven配置操作
1.修改为自己的maven路径 2.对应的自己的仓库设置
- LeetCode Shortest Unsorted Continuous Subarray
原题链接在这里:https://leetcode.com/problems/shortest-unsorted-continuous-subarray/description/ 题目: Given a ...
- 【LeetCode】002 Add Two Numbers
题目: You are given two non-empty linked lists representing two non-negative integers. The digits are ...
- 九、python沉淀之路--递归、全局变量、局部变量、作用域
一.递归 1.递归函数,同时使用嵌套,并且是将别的函数作用于调用函数里面 例1 num = [1,2,3,4,5] def add_one(i): return i+1 def reduce(i): ...
- redis 双写一致性问题
首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用.在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作. 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存.又或者 ...
- 媒体查询ipad,pc端
媒体查询 /* 判断ipad */ @media only screen and (min-device-width : 768px) and (max-device-width : 1024px){ ...
- ODP.NET OracleBulkCopy
using System;using System.Collections.Generic;using System.Linq;using System.Text;using Oracle.DataA ...
- Extjs5.0 学习之路【资源篇】
磨刀不误砍柴工. 先收集资源,然后再开始学习之路. Extjs5.0 文件下载 API-5.0 API离线包 http://cdn.sencha.com/downloads/docs/ext-docs ...
- Day3-Python基础3--默认参数和参数组
一.默认参数 先看下下面的代码: def stu_register(name,age,country,course): print("----注册学生信息------") prin ...