codeforces733E LCA在线
来源:互联网 发布:树莓派安装rpm软件 编辑:程序博客网 时间:2024/06/10 20:24
题目链接如下:http://codeforces.com/problemset/problem/733/F
算法思路
这道题让我又加深了一下对于倍增二分求LCA的原理.
很显然,要让每两个城市之间两两可达,需要构造一棵最小生成树。但是我们在这里可以使用一定的钱减少一些边的dissatisfation,而且这个值可以为负值,很显然我们要选择的就是成本最小的那一条边.这样的话,我们先使用最小生成树算法构造出最小生成树,然后对于每条边,加入最小生成树之后会构成环,所以对于每个环,我们要计算出这个环上权值最大的边。
这里使用的就是倍增,二分的方法,dp[i][j]表示的是第i个结点以上
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<utility>#include<vector>using namespace std;#define MAXN 200005#define LL long long#define INF 0x3f3f3f3f3f3f3f3fstruct Edge{ int u,v; int index; LL c,w;}EdgeTable[MAXN];int n,m;LL k,tot;vector<pair<int,int> >grid[MAXN];int fa[MAXN];int height[MAXN],psb[MAXN][22];LL dsb[MAXN][22];bool comp(Edge a,Edge b){ return a.w<b.w;}int find_dad(int cur){ if(fa[cur]==cur)return cur; else return fa[cur]=find_dad(fa[cur]);}void Kruskal(){ int i; int num=0; sort(EdgeTable+1,EdgeTable+1+m,comp); tot=0; for(i=1;i<=n;i++) fa[i] = i; for(i=1;i<=m;i++){ int u = EdgeTable[i].u; int v = EdgeTable[i].v; int fau = find_dad(u); int fav = find_dad(v); if(fau == fav)continue; else{ tot += EdgeTable[i].w; fa[fau] = fav; grid[u].push_back(make_pair(v,i)); grid[v].push_back(make_pair(u,i)); num++; if(num==n-1)break; } } return;}void Dfs(int cur,int fa){ int i,j,k; for(i=0;i<grid[cur].size();i++){ j = grid[cur][i].first; k = grid[cur][i].second; if(j!=fa){ height[j] = height[cur]+1; psb[j][0] = cur; dsb[j][0] = EdgeTable[k].w; Dfs(j,cur); } } return;}LL query(int a,int b){ int i=0; LL ans = 0; if(height[a]>height[b])return query(b,a); for(i=19;i>=0;i--){ if(height[b]-(1<<i)>=height[a]){ ans = max(ans,dsb[b][i]); b = psb[b][i]; } } if(a==b)return ans; for(i=19;i>=0;i--){ if(psb[a][i]!=psb[b][i]){ ans = max(dsb[a][i],ans); ans = max(dsb[b][i],ans); a = psb[a][i]; b = psb[b][i]; } } return max(ans,max(dsb[a][0],dsb[b][0]));}void Solve(){ memset(psb,-1,sizeof(psb)); Kruskal(); height[1]=1; Dfs(1,-1); int i,j; LL ans = INF; int select = 1; for(i=1;i<20;i++){ for(j=1;j<=n;j++){ if(psb[j][i-1]>=0){ psb[j][i] = psb[psb[j][i-1]][i-1]; dsb[j][i] = max(dsb[j][i-1],dsb[psb[j][i-1]][i-1]); } } } for(i=1;i<=m;i++){ //cout << ans << endl; LL tmp = tot - query(EdgeTable[i].u,EdgeTable[i].v) - k/EdgeTable[i].c + EdgeTable[i].w; if(tmp<ans){ ans = tmp; select = i; } } printf("%lld\n",ans); for(i=1;i<=n;i++) fa[i]=i; fa[EdgeTable[select].u] = EdgeTable[select].v; printf("%d %lld\n",EdgeTable[select].index,EdgeTable[select].w-k/EdgeTable[select].c); int num=1; for(i=1;i<=m;i++){ int u = EdgeTable[i].u; int v = EdgeTable[i].v; int fau = find_dad(u); int fav = find_dad(v); if(fau == fav)continue; else{ printf("%d %lld\n",EdgeTable[i].index,EdgeTable[i].w); fa[fau] = fav; num++; if(num==n-1)break; } } return;}int main(){ //freopen("input","r",stdin); int i; scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%lld",&EdgeTable[i].w); EdgeTable[i].index=i; } for(i=1;i<=m;i++) scanf("%lld",&EdgeTable[i].c); for(i=1;i<=m;i++) scanf("%d%d",&EdgeTable[i].u,&EdgeTable[i].v); scanf("%lld",&k); Solve(); return 0;}
0 0
- codeforces733E LCA在线
- 在线LCA
- poj3237 暴力在线LCA
- LCA在线算法
- LCA 在线算法
- POJ 2763 在线lca
- 在线LCA倍增法
- 在线LCA算法
- hdu_4547_CD操作(在线LCA)
- 在线lca算法模板
- RMQ在线求LCA
- LCA在线算法
- ZOJ2838【LCA在线查询】
- HDU2586【LCA在线算法】
- LCA在线算法
- lca 在线模板讲解
- LCA在线算法(hdu2586)
- LCA离线+在线+hdu2586(模板)
- uboot编译bug
- 原码、反码和补码
- wireshark抓包图解 TCP三次握手/四次挥手
- Eclipse下通过Maven的Jetty插件运行Web工程的配置,包括启动https
- MySQL执行计划解读
- codeforces733E LCA在线
- 单例模式的几种实现方式比较
- 实现Android5.0过渡动画兼容库
- Nov week1
- PMP学习笔记之第四章 项目整合管理
- STM32 USART寄存器方式编程
- ⑦基于时间型SQL盲注
- 【Codeforces 733F】 Drivers Dissatisfaction 【MST+bianry lifting】
- 关于Flux的学习