F - Drivers Dissatisfaction

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

思路:因为一条边的权重没有下限所以s元肯定是用在一条边上的。 那么我们先跑一个最小生成树,把这棵最小生成树建出来,然后我们枚举用了

s元之后的边,如果这条边不在树上那么加上这条边之后肯定形成了一个环,最优的方案肯定是删掉这个环中权值最大的边再次变成一棵树。

对于边(u,v)来说,如果把这条边加上,那么删掉的边肯定在,u到 lca(u,v) 和 v到 lca(u,v)中的权值最大的那条边。 可以用倍增快速找边,就能解决

这个问题啦。  码起来好麻烦啊,借鉴了某个学长的代码。。

 #include<bits/stdc++.h>
#define fi first
#define se second
#define mk make_pair
#define ll long long
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define read(x) scanf("%d",&x)
#define sread(x) scanf("%s",x)
#define dread(x) scanf("%lf",&x)
#define lread(x) scanf("%lld",&x)
using namespace std; const int N=2e5+;
const int M=2e6+;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+; int n,m,tot,s,fa[N],depth[N],nx[N][],mx[N][]; struct node
{
int u,v,w,c,id;
bool operator < (const node &rhs)const
{
return w<rhs.w;
}
}e[N<<]; bool cmp(node a,node b){
return a.id<b.id;
}
vector<pii> edge[N];
map<int,int> result; int Find(int x) {
return x==fa[x]? x : fa[x]=Find(fa[x]);
} ll kruscal()
{
ll ans=;
for(int i=;i<=n;i++)
fa[i]=i; sort(e,e+m); for(int i=;i<m;i++)
{
int u=e[i].u,v=e[i].v,w=e[i].w;
int nx_u=Find(u);
int nx_v=Find(v);
if(nx_u!=nx_v)
{
edge[u].push_back(mk(v,e[i].id));
edge[v].push_back(mk(u,e[i].id)); fa[nx_u]=nx_v;
ans+=w;
result[e[i].id]=w;
}
} sort(e,e+m,cmp); return ans;
} int getMxId(int a,int b)
{
if(a==-) return b;
if(b==-) return a;
return e[a].w>e[b].w? a : b;
}
void dfs(int u,int pre)
{
nx[u][]=pre;
for(int i=;i<;i++)
{
if(nx[u][i-]!=-)
{
nx[u][i]=nx[nx[u][i-]][i-];
mx[u][i]=getMxId(mx[u][i-],mx[nx[u][i-]][i-]);
}
else
nx[u][i]=mx[u][i]=-;
} for(auto t : edge[u])
{
int v=t.first;
if(v==pre)
continue;
depth[v]=depth[u]+;
mx[v][]=t.second; dfs(v,u);
}
} int getLca(int a,int b)
{
if(depth[a]<depth[b])
swap(a,b);
for(int i=;i<;i++)
if(depth[a]-depth[b]>>i & )
a=nx[a][i]; if(a==b) return a;
for(int i=;i>=;i--)
if(nx[a][i]!=nx[b][i])
a=nx[a][i],b=nx[b][i]; return nx[a][];
} int getMxIdPath(int a,int b)
{
int lca=getLca(a,b);
int ret=-;
for(int i=;i>=;i--)
{
if(nx[a][i]!=- && depth[nx[a][i]]>=depth[lca])
{
ret=getMxId(ret,mx[a][i]);
a=nx[a][i];
}
if(nx[b][i]!=- && depth[nx[b][i]]>=depth[lca])
{
ret=getMxId(ret,mx[b][i]);
b=nx[b][i];
}
}
return ret;
} int main()
{
read(n); read(m); for(int i=;i<m;i++)
read(e[i].w); for(int i=;i<m;i++)
read(e[i].c); for(int i=;i<m;i++)
{
read(e[i].u);
read(e[i].v);
e[i].id=i;
} read(s); ll cost=kruscal(); dfs(,-); ll ans=cost, p=; for(int id=;id<m;id++)
{
int big=getMxIdPath(e[id].u,e[id].v);
ll tmp=cost-e[big].w+e[id].w-s/e[id].c;
if(tmp<ans)
ans=tmp,p=id;
} printf("%lld\n",ans);
result.erase(getMxIdPath(e[p].u,e[p].v));
result[p]=e[p].w-s/e[p].c; for(auto t: result)
printf("%d %d\n",t.first+,t.second); return ;
}
/*
*/

Codeforces Round #378 (Div. 2) F - Drivers Dissatisfaction的更多相关文章

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

    http://codeforces.com/contest/733/problem/F 题意:给你一些城市和一些路,每条路有不满意程度和每减少一点不满意程度的花费,给出最大花费,要求找出花费小于s的最 ...

  2. Codeforces Round #378 (Div. 2)F

    题目:一个带权连通无向图,给第i条边权值减1需要花费ci元,你一共有S元,求最小生成树. 容易得出钱全部花在一条边上是最优的. 我们先做一遍最小生成树. 然后我们枚举减哪一条边. 如果这条边是树上的, ...

  3. codeforce 378 div 2 F —— Drivers Dissatisfaction (最小生成树,LCA,倍增)

    官方题解: If you choose any n - 1 roads then price of reducing overall dissatisfaction is equal to min(c ...

  4. Codeforces Round #485 (Div. 2) F. AND Graph

    Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...

  5. Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

    Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...

  6. Codeforces Round #501 (Div. 3) F. Bracket Substring

    题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...

  7. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  8. Codeforces Round #378 (Div. 2) D题(data structure)解题报告

    题目地址 先简单的总结一下这次CF,前两道题非常的水,可是第一题又是因为自己想的不够周到而被Hack了一次(或许也应该感谢这个hack我的人,使我没有最后在赛后测试中WA).做到C题时看到题目情况非常 ...

  9. Codeforces Round #376 (Div. 2)F. Video Cards(前缀和)

    题目链接:http://codeforces.com/contest/731/problem/F 题意:有n个数,从里面选出来一个作为第一个,然后剩下的数要满足是这个数的倍数,如果不是,只能减小为他的 ...

随机推荐

  1. AtCoder Grand Contest 008

    AtCoder Grand Contest 008 A - Simple Calculator 翻译 有一个计算器,上面有一个显示按钮和两个其他的按钮.初始时,计算器上显示的数字是\(x\),现在想把 ...

  2. Python multiprocessing模块的Pool类来代表进程池对象

    #-*-coding:utf-8-*- '''multiprocessing模块提供了一个Pool类来代表进程池对象 1.Pool可以提供指定数量的进程供用户调用,默认大小是CPU的核心数: 2.当有 ...

  3. 前端学习 -- Css -- 定义列表

    定义列表用来对一些词汇或内容进行定义 使用dl来创建一个定义列表 dl中有两个子标签 dt : 被定义的内容 dd : 对定义内容的描述 同样dl和ul和ol之间都可以互相嵌套 <!DOCTYP ...

  4. python 基础数据类型之list

    python 基础数据类型之list: 1.列表的创建 list1 = ['hello', 'world', 1997, 2000] list2 = [1, 2, 3, 4, 5 ] list3 = ...

  5. nodemon:让node自动重启

    nodemon:服务器自动重启工具 当我们修改代码时,node必须要手动重启,但可以按照nodemon. npm install -g nodemon 安装完 nodemon 后,就可以用 nodem ...

  6. bzoj千题计划215:bzoj1047: [HAOI2007]理想的正方形

    http://www.lydsy.com/JudgeOnline/problem.php?id=1047 先用单调队列求出每横着n个最大值 再在里面用单调队列求出每竖着n个的最大值 这样一个位置就代表 ...

  7. [转载] PNG优化插件:TinyPNG for Photoshop CC

    http://www.im286.com/thread-14922316-1-1.html http://www.tinypng.com的PS插件版,优化.无损压缩PNG,支持批量处理,据说只支持Ph ...

  8. HDU 2680 Choose the best route 最短路问题

    题目描述:Kiki想去他的一个朋友家,他的朋友家包括所有的公交站点一共有n 个,一共有m条线路,线路都是单向的,然后Kiki可以在他附近的几个公交站乘车,求最短的路径长度是多少. 解题报告:这道题的特 ...

  9. [转]GCC系列: __attribute__((visibility("")))

    在 objc-api.h 里面有很多关于__attribute__ 的定义. 例如 #if !defined(OBJC_VISIBLE) # if TARGET_OS_WIN32 # if defin ...

  10. 2017/05/22 java 基础 随笔

    多态:一种事物多种形态 前提:1.子父类继承关系 2.方法复写.重写 3.父类引用指向子类对象 成员变量: package com.huawei; public class Demo1 { publi ...