F. Drivers Dissatisfaction

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

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.

Input

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.

Output

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.

Examples
input
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
output
0
1 1
3 1
6 1
7 2
8 -5
input
3 3
9 5 1
7 7 2
2 1
3 1
3 2
2
output
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【链剖】【最小生成树应用】的更多相关文章

  1. Drivers Dissatisfaction

    Drivers Dissatisfaction time limit per test 4 seconds memory limit per test 256 megabytes input stan ...

  2. Codeforces Round #378 (Div. 2) F - Drivers Dissatisfaction

    F - Drivers Dissatisfaction 题目大意:给你n个点,m条边,每个边都有一个权重w,每条边也有一个c表示,消耗c元可以把这条边的权重减1,求最多消耗s元的最小生成树. 思路:因 ...

  3. 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】

    P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...

  4. 链剖&LCT总结

    在搞LCT之前,我们不妨再看看喜闻乐见的树链剖分. 树链剖分有一道喜闻乐见的例题:NOI2015 软件包管理器 如果你看懂题目了,你就会明白它是叫你维护一个树,这棵树是不会动的,要兹磁子树求和,子树修 ...

  5. BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)

    潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...

  6. CF487E Tourists(圆方树+堆+链剖)

    本题解并不提供圆方树讲解. 所以不会圆方树的出门右转问yyb 没有修改的话圆方树+链剖. 方点的权值为点双连通分量里的最小值. 然后修改的话圆点照修,每一个方点维护一个小根堆. 考虑到可能被菊花卡死. ...

  7. BZOJ 1146 二分+链剖+线段树+treap

    思路: 恶心的数据结构题-- 首先 我们 链剖 把树 变成序列 再 套一个 区间 第K大就好了-- 复杂度(n*log^4n) //By SiriusRen #include <cstdio&g ...

  8. 链剖-进阶ing-填坑-NOIP2013-货车运输

    This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://ww ...

  9. 链剖-What you are?-大话西游-校内oj2440

    This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://ww ...

随机推荐

  1. 【转】assert预处理宏与预处理变量

    assert assert是一个预处理宏,由预处理器管理而非编译器管理,所以使用时都不用命名空间声明,如果你写成std::assert反而是错的.使用assert需要包含cassert或assert. ...

  2. mysql字符串 转 int-double CAST与CONVERT 函数的用法

    MySQL 的CAST()和CONVERT()函数可用来获取一个类型的值,并产生另一个类型的值.两者具体的语法如下: CAST(value as type); CONVERT(value, type) ...

  3. sqlserver 无法获得数据库独占权

    ALTER DATABASE trqxs_cs SET OFFLINE WITH ROLLBACK IMMEDIATE

  4. php获取POST数据的三种方法

    方法一,$_POST $_POST或$_REQUEST存放的是PHP以key=>value的形式格式化以后的数据. $_POST方式是通过 HTTP POST 方法传递的变量组成的数组,是自动全 ...

  5. vue系列之项目结构

    参考地址:链接 build webpack配置相关 config webpack配置相关 node_modules  npm install 安装的依赖代码库 src  存放项目源码 static 存 ...

  6. 在 Win 7或8 下使用 VirtualBOX 虚拟机安装 OS X 10.11 El Capitan 及 Xcode 7.0

    注:本文源自于: http://bbs.feng.com/read-htm-tid-9908410.html _____________________________________________ ...

  7. JFreeChart入门

    JFreeChart主要用来各种各样的图表,这些图表包括:饼图.柱状图(普通柱状图以及堆栈柱状图).线图.区域图.分布图.混合图.甘特图以及一些仪表盘等等 (源代码下载) 示例程序运用的jar包: j ...

  8. Inno Setup 系列之先卸载之后再安装

    需求使用Inno Setup打包程序之后,很多时候我们需要在安装文件之前卸载原有的程序而不是覆盖安装,本文的Code就是实现了这样的功能.如果想要在安装前先卸载,那么需要加下面代码,需要注意的是双星号 ...

  9. pytest七:assert

    断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了.什么是断言呢?简单来讲就是实际结果和期望结果去对比,符合预期那就测试 pass,不符合预期那就测试 failed py ...

  10. 【HTTP】 Fiddler简介

    1.为什么是Fiddler? 抓包工具有很多,小到最常用的web调试工具firebug,达到通用的强大的抓包工具wireshark.为什么使用fiddler?原因如下: a.Firebug虽然可以抓包 ...