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 ≤ nai ≠ 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. Linux下rsyslog日志收集服务环境部署记录【转】

    rsyslog 可以理解为多线程增强版的syslog. 在syslog的基础上扩展了很多其他功能,如数据库支持(MySQL.PostgreSQL.Oracle等).日志内容筛选.定义日志格式模板等.目 ...

  2. 如何用enable_shared_from_this 来得到指向自身的shared_ptr 及对enable_shared_from_this 的理解

    在看<Linux多线程服务端编程:使用muduo C++网络库> 的时候,在说到如何防止在将对象的 this 指针作为返回值返回给了调用者时可能会造成的 core dump.需使用 ena ...

  3. saltstack自动化运维系列②之saltstack的数据系统

    saltstack自动化运维系列②之saltstack的数据系统 grains:搜集minion启动时的系统信息,只有在minion启动时才会搜集,grains更适合做一些静态的属性值的采集,例如设备 ...

  4. nagios系列(八)之nagios通过nsclient监控windows主机

    nagios通过nsclient监控windows主机 1.下载NSClient -0.3.8-Win32.rar安装在需要被监控的windows主机中 可以设置密码,此处密码留空 2.通过在nagi ...

  5. 批量监测dns是否可用脚本,不可用时并切换

    #!/usr/bin/env python # coding=utf-8 # hexm@2016-02-14 import time import requests import paramiko i ...

  6. selenium webdriver+python基本操作

    # -*- coding:utf-8 -*-#导入模块from selenium import webdriver from selenium.common.exceptions import NoS ...

  7. ural1855 线段树区间更新+推公式维护一元二次式

    和威威猫系列故事差不多,都是根据条件推出公式 /* 操作c a b d:a到b道路上的所有边权值加d 操作e a b:问a到b中包含的道路的平均权值 区间平均值=所有可能路径权值/所有路径数, 而路径 ...

  8. 《剑指offer》-判断平衡二叉树

    题目描述 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 考察平衡树的概念和递归的使用.平衡树是指,树中的每个节点的左右子树的高度差小于等于1. class Solution { public: bo ...

  9. 详解如何在 Linux 中安装最新的 Python 3.6 版本

    # 下载源码包安装,先装wget,或curl. yum install wget # 再安装解压缩和编译环境: yum install zlib-devel bzip2-devel openssl-d ...

  10. BZOJ1968 [Ahoi2005]COMMON 约数研究 数论

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1968 题意概括 求 ΣF(i)   (1<=i<=n)N<=1000000 F( ...