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 ...
随机推荐
- mac安装pyspider报错
(env)$ pip3 uninstall pycurl (env)$ pip3 install --upgrade pip (env)$ export LDFLAGS=-L/usr/local/op ...
- C++:__stdcall详解
原文地址:http://www.cnblogs.com/songfeixiang/p/3733661.html 对_stdcall 的理解(上)在C语言中,假设我们有这样的一个函数:int funct ...
- android手机访问app网页报错:net::ERR_PROXY_CONNECTION_FAILED
手机访问网页报错:net::ERR_PROXY_CONNECTION_FAILED 手机访问app中嵌入的html网页报错: net::ERR_PROXY_CONNECTION_FAILED 原来是手 ...
- Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
# yum install -y vim Loaded plugins: fastestmirror, presto Loading mirror speeds from cached hostfil ...
- linux网络设备驱动
Linux网络设备驱动 Linux网络驱动程序的体系结构可划分为4个层次.Linux内核源代码中提供了网络设备接口及以网络子系统的上层的代码,移植特定网络硬件的驱动程序的主要工作就是完成设备驱动功能层 ...
- 12-关于DOM操作的相关案例
1.模态框案例 需求: 打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框 代码如下: <!DOCTYPE html> <h ...
- mysql当查询某字段结果为空并赋值
1 代码 1.1 当当前字段为空,查询结果返回“none”,并且统计出现频率 select case when 字段 is null then 'none' else 字段 end as 字段, co ...
- ocp linux 基础要点
基本命令: 创建/修改/删除用户 useradd/usermod/userdel 创建/修改/删除用户组 groupadd/groupmod/groupdel 修改所属用户/所属用户 ...
- PHP数学常用函数
PHP数学常用函数 函数名 描述 实例 abs() 求绝对值 $abs = abs(-4.2); //4.2 fmod() 浮点数取余 $x = 5.7;$y = 1.3;$r = fmod($x, ...
- python 全栈开发,Day23(复习,isinstance和issubclass,反射)
一.复习 class A: def func1(self):pass def func2(self): pass def func3(self): pass a = A() b = A() print ...