CF733F Drivers Dissatisfaction【链剖】【最小生成树应用】
F. Drivers Dissatisfaction
4 seconds
256 megabytes
standard input
standard output
In one kingdom there are n cities and m two-way roads. Each road connects a pair of cities, and for each road we know the level of drivers dissatisfaction — the value wi.
For each road we know the value ci — how many lamziks we should spend to reduce the level of dissatisfaction with this road by one. Thus, to reduce the dissatisfaction with the i-th road by k, we should spend k·ci lamziks. And it is allowed for the dissatisfaction to become zero or even negative.
In accordance with the king's order, we need to choose n - 1 roads and make them the main roads. An important condition must hold: it should be possible to travel from any city to any other by the main roads.
The road ministry has a budget of S lamziks for the reform. The ministry is going to spend this budget for repair of some roads (to reduce the dissatisfaction with them), and then to choose the n - 1 main roads.
Help to spend the budget in such a way and then to choose the main roads so that the total dissatisfaction with the main roads will be as small as possible. The dissatisfaction with some roads can become negative. It is not necessary to spend whole budget S.
It is guaranteed that it is possible to travel from any city to any other using existing roads. Each road in the kingdom is a two-way road.
The first line contains two integers n and m (2 ≤ n ≤ 2·105, n - 1 ≤ m ≤ 2·105) — the number of cities and the number of roads in the kingdom, respectively.
The second line contains m integers w1, w2, ..., wm (1 ≤ wi ≤ 109), where wi is the drivers dissatisfaction with the i-th road.
The third line contains m integers c1, c2, ..., cm (1 ≤ ci ≤ 109), where ci is the cost (in lamziks) of reducing the dissatisfaction with the i-th road by one.
The next m lines contain the description of the roads. The i-th of this lines contain a pair of integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi) which mean that the i-th road connects cities ai and bi. All roads are two-way oriented so it is possible to move by the i-th road from aito bi, and vice versa. It is allowed that a pair of cities is connected by more than one road.
The last line contains one integer S (0 ≤ S ≤ 109) — the number of lamziks which we can spend for reforms.
In the first line print K — the minimum possible total dissatisfaction with main roads.
In each of the next n - 1 lines print two integers x, vx, which mean that the road x is among main roads and the road x, after the reform, has the level of dissatisfaction vx.
Consider that roads are numbered from 1 to m in the order as they are given in the input data. The edges can be printed in arbitrary order. If there are several answers, print any of them.
6 9
1 3 1 1 3 1 2 2 2
4 1 4 2 2 5 3 1 6
1 2
1 3
2 3
2 4
2 5
3 5
3 6
4 5
5 6
7
0
1 1
3 1
6 1
7 2
8 -5
3 3
9 5 1
7 7 2
2 1
3 1
3 2
2
5
3 0
2 5
Solution
题意:给一个无向图,每条边有一个边权$w$和一个费用$c$,你现在有$s$元,对于每条边可以选择花费$c$将这条边边权减少1(允许负边权),询问这种操作过后最小生成树的最小总权值以及树上的所有边和它们的权值。
思路很简单,明显可以把所有的花费全部砸在一条边上,可以首先建一棵最小生成树,如果把钱砸在树边,那么选择的一定是树边中$c$最小的那条,往死里减就可以了。
如果要砸在非树边上,那么就是在这条非树边两端点在树上的链中找到最长的边删除,用这条边代替即可。
主要是代码实现太复杂了!!!!(虽然我一次a掉嘻嘻嘻嘻嘻
捋清楚每条边的标号是最复杂的???链剖+线段树随便搞搞就好。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std; LL n, m, s; struct tree {
LL w, id;
tree operator + (const tree &a) const {
tree c;
if(a.w > w) c.w = a.w, c.id = a.id;
else c.w = w, c.id = id;
return c;
}
} TR[]; struct Node {
LL u, v, w, id, tag, nex;
} Edge[], Edge_inv[];
bool cmp(Node a, Node b) { return a.w < b.w; } LL h[], stot;
void add(LL u, LL v, LL w, LL id) {
Edge[++stot] = (Node) {u, v, w, id, , h[u]};
h[u] = stot;
} LL stot_inv;
void add_inv(LL u, LL v, LL w, LL id) {
Edge_inv[++stot_inv] = (Node) {u, v, w, id, , };
} LL fa[], dep[], siz[], son[], sw[], sid[];
void dfs1(LL u, LL f) {
fa[u] = f; dep[u] = dep[f] + ; siz[u] = ;
for(LL i = h[u]; i; i = Edge[i].nex) {
LL v = Edge[i].v;
if(v == f) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v, sw[u] = Edge[i].w, sid[u] = Edge[i].id;
}
} LL top[], seq[], seq1[], in[], idc;
void dfs2(LL u, LL t, LL w, LL id) {
top[u] = t; seq[++idc] = w; seq1[idc] = id, in[u] = idc;
if(son[u]) dfs2(son[u], t, sw[u], sid[u]);
for(LL i = h[u]; i; i = Edge[i].nex) {
LL v = Edge[i].v;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v, Edge[i].w, Edge[i].id);
}
} void update(LL nd) {
TR[nd] = TR[nd << ] + TR[nd << | ];
} void build(LL nd, LL l, LL r) {
if(l == r) {
TR[nd].w = seq[l];
TR[nd].id = seq1[l];
return ;
}
LL mid = (l + r) >> ;
build(nd << , l, mid); build(nd << | , mid + , r);
update(nd);
} tree query(LL nd, LL l, LL r, LL L, LL R) {
if(l >= L && r <= R) return TR[nd];
LL mid = (l + r) >> ; tree ans; ans.w = -0x3f3f3f3f, ans.id = ;
if(L <= mid) ans = ans + query(nd << , l, mid, L, R);
if(R > mid) ans = ans + query(nd << | , mid + , r, L, R);
return ans;
} tree query(LL u, LL v) {
tree ans; ans.w = -0x3f3f3f3f, ans.id = ;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ans = ans + query(, , n, in[top[u]], in[u]);
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
ans = ans + query(, , n, in[v] + , in[u]);
return ans;
} LL f[];
LL find(LL x) {
if(x != f[x]) f[x] = find(f[x]);
return f[x];
} LL w[], c[], tot, ans1, ans2;
void Kruskal() {
sort(Edge_inv + , Edge_inv + + m, cmp);
for(LL i = ; i <= n; i ++) f[i] = i;
for(LL i = ; i <= m; i ++) {
LL u = Edge_inv[i].u, v = Edge_inv[i].v, id = Edge_inv[i].id;
LL uu = find(u), vv = find(v);
if(uu != vv) {
Edge_inv[i].tag = ;
f[uu] = vv;
add(u, v, w[id], id); add(v, u, w[id], id);
tot += w[id];
if(c[id] < c[ans1]) ans1 = id;
}
}
} int main() {
scanf("%lld%lld", &n, &m);
for(LL i = ; i <= m; i ++) scanf("%lld", &w[i]);
for(LL i = ; i <= m; i ++) scanf("%lld", &c[i]); c[] = 0x3f3f3f3f;
for(LL i = ; i <= m; i ++) {
LL u, v;
scanf("%lld%lld", &u, &v);
add_inv(u, v, w[i], i);
}
scanf("%lld", &s);
Kruskal(); ans2 = tot - s / c[ans1];
dfs1(, ); dfs2(, , -0x3f3f3f3f, ); build(, , n);
LL flag = ;
for(LL i = ; i <= m; i ++) {
if(!Edge_inv[i].tag) {
LL u = Edge_inv[i].u, v = Edge_inv[i].v, id = Edge_inv[i].id;
tree a = query(u, v);
LL tmp = tot - a.w + w[id] - s / c[id];
if(tmp < ans2) ans1 = id, ans2 = tmp, flag = a.id;
}
}
printf("%lld\n", ans2);
for(LL i = ; i <= m; i ++) {
LL id = Edge_inv[i].id;
if(ans1 == id) {
printf("%lld %lld\n", id, w[id] - s / c[id]);
} else if(Edge_inv[i].tag) {
if(flag != id) {
printf("%lld %lld\n", id, w[id]);
}
}
}
return ;
}
CF733F Drivers Dissatisfaction【链剖】【最小生成树应用】的更多相关文章
- Drivers Dissatisfaction
Drivers Dissatisfaction time limit per test 4 seconds memory limit per test 256 megabytes input stan ...
- Codeforces Round #378 (Div. 2) F - Drivers Dissatisfaction
F - Drivers Dissatisfaction 题目大意:给你n个点,m条边,每个边都有一个权重w,每条边也有一个c表示,消耗c元可以把这条边的权重减1,求最多消耗s元的最小生成树. 思路:因 ...
- 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】
P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...
- 链剖&LCT总结
在搞LCT之前,我们不妨再看看喜闻乐见的树链剖分. 树链剖分有一道喜闻乐见的例题:NOI2015 软件包管理器 如果你看懂题目了,你就会明白它是叫你维护一个树,这棵树是不会动的,要兹磁子树求和,子树修 ...
- BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
- CF487E Tourists(圆方树+堆+链剖)
本题解并不提供圆方树讲解. 所以不会圆方树的出门右转问yyb 没有修改的话圆方树+链剖. 方点的权值为点双连通分量里的最小值. 然后修改的话圆点照修,每一个方点维护一个小根堆. 考虑到可能被菊花卡死. ...
- BZOJ 1146 二分+链剖+线段树+treap
思路: 恶心的数据结构题-- 首先 我们 链剖 把树 变成序列 再 套一个 区间 第K大就好了-- 复杂度(n*log^4n) //By SiriusRen #include <cstdio&g ...
- 链剖-进阶ing-填坑-NOIP2013-货车运输
This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://ww ...
- 链剖-What you are?-大话西游-校内oj2440
This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://ww ...
随机推荐
- nodejs 在线学习课堂
http://ww***/class/5359f6f6ec7452081a7873d8
- linux 平台core dump文件生成
1. 在终端中输入ulimit -c 如果结果为0,说明当程序崩溃时,系统并不能生成core dump. root@hbg:/# ulimit -c0root@hbg:/# 2.使用ulimit -c ...
- centos6.5环境基于conga的web图形化界面方式配置rhcs集群
一.简介 RHCS 即 RedHat Cluster Suite ,中文意思即红帽集群套件.红帽集群套件(RedHat Cluter Suite, RHCS)是一套综合的软件组件,可以通过在部署时采用 ...
- centos7.2环境编译安装mysql5.5.48
一.安装cmake编译工具 跨平台编译器 查看是否已经安装了gcc # rpm -qa | grep gcc # yum install -y gcc-c++ # yum install -y cma ...
- 百度地图的Icon
在百度地图的类说明中,查看对Icon的构建: 定制IconOptions 看下面的差别 发现在IconOptions没有imageSize属性 而在实际测试中,代码如下 <script type ...
- python之__dict__与dir(转载)
Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案. __dict__与dir()的区别: dir()是一个函数,返回的是list: __di ...
- Application.ProcessMessages; 的重要性
https://files.cnblogs.com/files/del88/登陆光标_悬赏50元.zip ----------------------------------------------- ...
- layer.js弹出框
HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- Collections.sort 给集合排序
List<MenuVo> child_menus = new ArrayList<MenuVo>(); for (MenuVo menuVo : child_menus) { ...
- 阿里巴巴的26款超神Java开源项目
目录 1.分布式应用服务开发的一站式解决方案 Spring Cloud Alibaba 2. JDBC 连接池.监控组件 Druid 3. Java 的 JSON 处理器 fastjson 4. 服务 ...