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. 【刷题】BZOJ 3512 DZY Loves Math IV

    Description 给定n,m,求 模10^9+7的值. Input 仅一行,两个整数n,m. Output 仅一行答案. Sample Input 100000 1000000000 Sampl ...

  2. 基于Docker持续交付平台建设的实践

    导读:中国五矿和阿里巴巴联手打造的钢铁服务专业平台五阿哥,通过集结阿里巴巴在大数据.电商平台和互联网产品技术上的优势,为终端用户带来一站式采购体验.本文是五阿哥运维技术团队针对Docker容器技术在如 ...

  3. Flash 解题报告

    Flash Description 给你一颗树,需要把每个点染色,每个点染色时间为\(t_i\),要求同时染色的点的集合为树的独立集,最小化染色结束时间之和. 其实题面蛮有趣的♂ HINT \(n\l ...

  4. psutil库

    psutil是一个非常强大的第三方库,用法简单,这里主要是做一下梳理. 先看看官方说明: psutil (python system and process utilities) is a cross ...

  5. INF文件详解

    安装信息(Setup Information)文件是Windows系统支持的一种安装信息存放文件,一般以INF作为扩展名,因此也叫INF文件.安装信息INF文件与Windows内建的安装服务引擎(AP ...

  6. 异步消息处理机制Handler

    Android 中的异步消息处理主要由四个部分组成,Message.Handler.MessageQueue 和Looper. 1. Message Message 是在线程之间传递的消息,它可以在内 ...

  7. bzoj千题计划257:bzoj4199: [Noi2015]品酒大会

    http://www.lydsy.com/JudgeOnline/problem.php?id=4199 求出后缀数组的height 从大到小枚举,合并 维护组内 元素个数,最大.次大.最小.次小 # ...

  8. IntelliJ IDEA 破解 - pycharm

    MAC激活方法 下载破解文件 下载地址: https://files.cnblogs.com/files/resn/JetbrainsCrack-2.7-release-str.jar.zip 或者去 ...

  9. koa1.x获取原始body内容

    Node版本比较老,koa1.x配合koa-body-parser,默认koa-body-parser会把请求数据转成json对象, 然而有的时候需要获取原始的内容,不要转换,看波koa-body-p ...

  10. HDU 2054 又见GCD

    又见GCD Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...