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. CentOS安装git及使用Gitolite来管理版本库

    首先吐槽一下网上的各种教程,大部分都扯蛋,估计都是些所谓的"编辑"在网上瞎抄来的-- 以下内容都是基于CentOS的服务器端,Mac OS X的客户端. 如果是使用的Windows ...

  2. 解题:HNOI 2015 开店

    题面 根据树上距离的计算方法,可以先把答案化成$\sum dep_i+n*dep_u-\sum 2*dep[LCA(i,u)]$的形式,然后维护$\sum 2*dep[LCA(i,u)]$ 把妖怪们按 ...

  3. python中的无参装饰器和有参装饰器

    python中的无参装饰器和有参装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 装饰器特点: 1>.开放封闭原则,即对扩展是开放的,对修改时封闭的: 2>.装饰器 ...

  4. mongodb与mysql的区别与具体应用场景

    MongoDB: 非关系型数据库,文档型数据库, 文档型数据库:可以存放xml,json,bson类型的数据.这些数据具备自述性(self-describing),呈现分层的树状数据结构.数据结构由键 ...

  5. CSS Counter Style试玩儿

    2015年2月3日,CSS Counter Style level3成为了W3C的候选标准,是时候来一探究竟,看看强大魔力的@counter-style如何自定义list-style和counter. ...

  6. Linux命令(一)grep查询

    grep -n as test1.txt -n : 显示行号 -v: 显示没有搜索字符的一行 -i:忽视大小写  搜索字符串 模式查找

  7. Spring Mvc + Maven + BlazeDS 与 Flex 通讯 (七)

    BlazeDS 说明 BlazeDS是由Adobe开源的基于amf协议的,用于解决flex与java通讯的组件; 基于传统的文本协议的XML传输方式,在抽象层方面会有很大的压力,特别在需要序列化与反序 ...

  8. 20155314 2016-2017-2 《Java程序设计》第8周学习总结

    20155314 2016-2017-2 <Java程序设计>第8周学习总结 教材学习内容总结 了解NIO 会使用Channel.Buffer与NIO2 会使用日志API.国际化 会使用正 ...

  9. c++刷题(43/100)矩阵旋转打印

    题目1:矩阵旋转打印 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则 ...

  10. 云计算--hbase shell

    具体的 HBase Shell 命令如下表 1.1-1 所示: 下面我们将以“一个学生成绩表”的例子来详细介绍常用的 HBase 命令及其使用方法. 这里 grad 对于表来说是一个列,course ...