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 ...
随机推荐
- Project://CRM
初始化 考勤 录入成绩 查看成绩 待续...
- Django 框架概况
Django 里更关注的是模型(Model).模板(Template)和视图(Views),称为 MTV模式: M 代表模型(Model),即数据存取层. 该层处理与数据相关的所有事务:如何存取.如何 ...
- 转载:java电商面试介绍(不完整版)
转载: http://blog.csdn.net/xue_mind/article/details/52959107
- bzoj 3887: Grass Cownoisseur Tarjan+Topusort
题目: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) 题解: 首先考虑简单 ...
- Day2-Python基础2---浅copy、深copy的差别
浅copy 首先我们来看下面一段代码: 1 >>> names = ["maqing"," peilin"," xiaoming&q ...
- HTML5离线应用
本地缓存与浏览器缓存 本地缓存是为整个web应用程序服务的而网页缓存值服务与单个网页 本地缓存是为你指定的资源进行缓存,而我们不知道网页缓存会春初哪些内容,他是不安全不可靠的 在没有网络的时候还是可以 ...
- 获取APK的package名和activity名
使用 aapt dump badging + 需要安装的APK
- Java-API-Package:javax.http.servlet
ylbtech-Java-API-Package:javax.http.servlet 1.返回顶部 1. Package javax.servlet.http This chapter descri ...
- JavaScript基本概念A
简介 如果需要了解这些概念, 您应该熟悉 JS 的基本知识. 弱类型 在也无需绞尽脑汁觉得到底采用 float.double,int 还是 short 或是 long 还是 String.只需这样定义 ...
- Solaris11修改主机名
在Solaris10中,主机名的修改是通过修改相关的配置文件实现的.在Solaris11中,主机名的配置信息已经转移到SMF配置库中,因此修改主机名的方式与Solaris10完全不同.以下是修改Sol ...