http://codeforces.com/problemset/problem/733/F (题目链接)

题意

  给出一张n个点的无向图,每一条变有两个特征值:${w,c}$;分别表示这条边的权值为${w}$,每将这条边的权值减小1需要充${c}$元钱。初始时有${S}$元钱,你可以对任意边充钱使得它的权值${w}$减少,甚至减成负数。现在需要你选出若干条边,使得所有的点都联通并且这些边的权值和在“充了钱”之后最小。

Solution

  codeforces上的题目真是良心题。

  想一想,假设我们已经选出了一些边,如果我们“充钱”,反正充哪条边都是只能使最终答案减小1,不如就抓着其中一条${c}$最小的边一通狂充,不充钱还想跟我玩?于是我们就很容易得到一个初始想法:跑一遍关于${w}$的最小生成树,然后狂减${c}$最小的边,得到一个初始答案${ans}$。

  考虑这样一种情况:可能存在一条不在最小生成树的边,但是它的${c}$比最小生成树中的边的${c}$都要小,我们可以将它选入答案并通过对它“充钱”,使答案更优。

  这样的情况怎么处理呢?我们枚举每一条不在最小生成树中并且${c}$符合要求的边,尝试将它加入生成树中。加入一条边${(u,v)}$,那么必定要删掉树上一条边,那么删去的这条边一定是树上${u,v}$间${w}$最大的一条边,此时我们不用考虑树中的边的${c}$,因为如果我们要“充钱”一定是对新加入的这条边充,如果最后剩下的钱小于新加入这条边的${c}$,那么显然剩下的钱已经不能再做出贡献了。

  那么现在问题就是如何快速查询树上两点间的最长边,是不是很熟悉,没错就是NOIP2013货车运输,直接树上倍增即可。

细节

  记得开long long。然后方案的统计有点麻烦,注意不要写错,Wa on test 100,莫名其妙过了前面99个点,这是要FST的节奏啊→_→。

代码

// codeforces 733F
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define MOD 99999997
#define inf 2000000000
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=200010;
struct edge {int to,next,w,id;}e[maxn<<1];
struct data {int u,v,w,c,id;}a[maxn];
int f[maxn],head[maxn],fa[maxn][30],bin[30],d[maxn][30],deep[maxn],b[maxn];
int cnt,S,n,m,prt[maxn],pp[maxn]; bool cmp(data a,data b) {
return a.w<b.w;
}
int maxw(int x,int y) {
return a[x].w<a[y].w ? y : x;
}
int find(int x) {
return x==f[x] ? x : f[x]=find(f[x]);
}
void link(int u,int v,int w) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void dfs(int x) {
for (int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for (int i=1;i<=20;i++) d[x][i]=maxw(d[x][i-1],d[fa[x][i-1]][i-1]);
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
deep[e[i].to]=deep[x]+1;
d[e[i].to][0]=e[i].w;
fa[e[i].to][0]=x;
dfs(e[i].to);
}
}
int lca(int x,int y) {
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=0;bin[i]<=t;i++) if (bin[i]&t) x=fa[x][i];
for (int i=20;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return x==y ? x : fa[x][0];
}
int query(int x,int f) {
int t=deep[x]-deep[f];
int res=0;
for (int i=0;bin[i]<=t;i++) if (bin[i]&t) res=maxw(res,d[x][i]),x=fa[x][i];
return res;
}
int main() {
bin[0]=1;for (int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d",&a[i].w);
for (int i=1;i<=m;i++) scanf("%d",&a[i].c);
for (int i=1;i<=m;i++) scanf("%d%d",&a[i].u,&a[i].v),a[i].id=i;
scanf("%d",&S);
sort(a+1,a+1+m,cmp);
for (int i=1;i<=n;i++) f[i]=i;
int C=inf;
LL ans=0,tot=0;int num=0,dl=0;
for (int i=1;i<=m;i++) {
int r1=find(a[i].u),r2=find(a[i].v);
if (r1!=r2) {
link(a[i].u,a[i].v,i);
f[r1]=r2;
b[i]=1;
tot+=(LL)a[i].w;
if (a[i].c<C) C=a[i].c,num=i;
}
}
ans=tot-S/C;
dfs(1);
for (int i=1;i<=m;i++) if (a[i].c<C) {
int ff=lca(a[i].u,a[i].v);
int x=maxw(query(a[i].u,ff),query(a[i].v,ff));
LL tmp=(LL)tot-a[x].w+a[i].w-S/a[i].c;
if (ans>tmp) {
ans=tmp;b[dl]=1;b[num]=0;b[dl=x]=0;num=i;b[i]=1;}
}
printf("%lld\n",ans);
for (int i=1;i<=m;i++) if (b[i]) {
int x=num==i ? S/a[i].c : 0;
prt[a[i].id]=a[i].w-x;
pp[a[i].id]=1;
}
for (int i=1;i<=m;i++) if (pp[i]) printf("%d %d\n",i,prt[i]);
return 0;
}

  

【codeforces 733F】 Drivers Dissatisfaction的更多相关文章

  1. 【codeforces 733F】Drivers Dissatisfaction

    [题目链接]:http://codeforces.com/problemset/problem/733/F [题意] 给你n个点m条边; 让你从中选出n-1条边; 形成一个生成树; (即让n个点都联通 ...

  2. 【codeforces 415D】Mashmokh and ACM(普通dp)

    [codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...

  3. 【codeforces 707E】Garlands

    [题目链接]:http://codeforces.com/contest/707/problem/E [题意] 给你一个n*m的方阵; 里面有k个联通块; 这k个联通块,每个连通块里面都是灯; 给你q ...

  4. 【codeforces 707C】Pythagorean Triples

    [题目链接]:http://codeforces.com/contest/707/problem/C [题意] 给你一个数字n; 问你这个数字是不是某个三角形的一条边; 如果是让你输出另外两条边的大小 ...

  5. 【codeforces 709D】Recover the String

    [题目链接]:http://codeforces.com/problemset/problem/709/D [题意] 给你一个序列; 给出01子列和10子列和00子列以及11子列的个数; 然后让你输出 ...

  6. 【codeforces 709B】Checkpoints

    [题目链接]:http://codeforces.com/contest/709/problem/B [题意] 让你从起点开始走过n-1个点(至少n-1个) 问你最少走多远; [题解] 肯定不多走啊; ...

  7. 【codeforces 709C】Letters Cyclic Shift

    [题目链接]:http://codeforces.com/contest/709/problem/C [题意] 让你改变一个字符串的子集(连续的一段); ->这一段的每个字符的字母都变成之前的一 ...

  8. 【Codeforces 429D】 Tricky Function

    [题目链接] http://codeforces.com/problemset/problem/429/D [算法] 令Si = A1 + A2 + ... + Ai(A的前缀和) 则g(i,j) = ...

  9. 【Codeforces 670C】 Cinema

    [题目链接] http://codeforces.com/contest/670/problem/C [算法] 离散化 [代码] #include<bits/stdc++.h> using ...

随机推荐

  1. Java集合系列:-----------05LinkedList的底层实现

    前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类--LinkedList.和学习ArrayList一样,接下来呢,我们先对LinkedList ...

  2. BZOJ 1096 【ZJOI2007】 仓库建设

    Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天, ...

  3. Android开发之旅: Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

  4. 利用mybatis-generator自动生成代码

    mybatis-generator有三种用法:命令行.eclipse插件.maven插件.个人觉得maven插件最方便,可以在eclipse/intellij idea等ide上可以通用. 下面是从官 ...

  5. vmware安装cent os 6.5 + oracle 11g xe + jboss eap 6.2 + weblogic 12c+ webshpere mq 7.5

    前言: mac系统发展速度确实很快,短短数年,mac os上已经能网银支付(中行.招行.工商.支付宝等均已全面支持mac os了),windows上的经典常用软件:qq.飞信.旺旺.有道词典.有道云笔 ...

  6. PhoneGap: Android平台入门例子(Hello World)

    Hello World Demo: http://docs.phonegap.com/en/2.0.0/guide_getting-started_android_index.md.html#Gett ...

  7. visual studio 2012 的制作ActiveX、打包和发布

    开发环境是Vs 2012  Framework 4.0 源码和制作工具在文章最下边 一. ActiveX控件Demo 新建一个Window窗体控件库项目 在自动生成的UserControl1页面上添加 ...

  8. jquery 使用方法(转)

    原文: http://www.cnblogs.com/Chenfengtao/archive/2012/01/12/2320490.html jQuery是目前使用最广泛的javascript函数库. ...

  9. nios II--实验2——led硬件部分

    Led 硬件开发 新建原理图 1.打开Quartus II 11.0,新建一个工程,File -> New Project Wizard…,忽略Introduction,之间单击 Next> ...

  10. [BZOJ1854][Scoi2010]游戏(二分图匹配/并查集)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1854 分析:很裸的一道二分图匹配对吧,但是在hzwer的blog上看见神奇的并查集做法 ...