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 ...
随机推荐
- linux 串口0x03,0x13的问题【转】
linux 串口0x03,0x13的问题 本人最近在调linux串口的时候,发现其他数据接收正常,但是0x13怎么也接收不到,后面发现了这篇文章,两天的bug终于解决了,原来是linux底层uart配 ...
- Redis消息通知(任务队列和发布订阅模式)
Redis学习笔记(十)消息通知(任务队列和发布订阅模式) 1. 任务队列 1.1 任务队列的特点 任务队列:顾名思义,就是“传递消息的队列”.与任务队列进行交互的实体有两类,一类是生产者(produ ...
- C++:vector的用法详解
原文地址:http://blog.csdn.net/hancunai0017/article/details/7032383 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于 ...
- lvs持久连接及防火墙标记实现多端口绑定服务
lvs持久连接及防火墙标记实现多端口绑定服务 LVS持久连接: PCC:将来自于同一个客户端发往VIP的所有请求统统定向至同一个RS: PPC:将来自于一个客户端发往某VIP的某端口的所有请求统统定向 ...
- PYTHON-迭代器,xxx生成式
一 迭代器1 什么是迭代器 #迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 while True: #只是单纯地重复,因而 ...
- Fiddler抓包9-保存会话(save)
前言 为什么要保存会话呢?举个很简单的场景,你在上海测试某个功能接口的时候,发现了一个BUG,而开发这个接口的开发人员是北京的一家合作公司.你这时候给对方开发提bug, 如何显得专业一点,能让对方心服 ...
- pytest六:parametrize-参数化
pytest.mark.parametrize 装饰器可以实现测试用例参数化. 1.这里是一个实现检查一定的输入和期望输出测试功能的典型例子 import pytest @pytest.mark.pa ...
- python 全栈开发,Day43(python全栈11期月考题)
python全栈11期月考题 1.常用字符串格式化有哪些?并说明他们的区别 2.请手写一个单例模式(面试题) 3.利用 python 打印前一天的本地时间,格式为‘2018-01-30’(面试题) 4 ...
- JQuery动画详解(四)
一:基本动画show()显示隐藏的匹配元素.这个就是 'show( speed, [callback] )' 无动画的版本.如果选择的元素是可见的,这个方法将不会改变任何东西.无论这个元素是通过hid ...
- [转] 深入理解React 组件状态(State)
React 的核心思想是组件化的思想,应用由组件搭建而成,而组件中最重要的概念是State(状态),State是一个组件的UI数据模型,是组件渲染时的数据依据. 一. 如何定义State 定义一个合适 ...