NOIP 2015 Day2 T3 运输计划(二分+dfs序+树上差分+倍增LCA)
来源:互联网 发布:全国网络诈骗报警中心 编辑:程序博客网 时间:2024/05/29 16:04
题目大意:给你一棵n个点的边带权树,再给树上m条路径,让你将一条边权改为0,使得最后路径的最大值最小
题解:
1、对于求最大值最小,首先想到二分答案,想了想发现没毛病,怎么验证;
2、考虑每次找出比当前二分的值大的路径,想将一条他们都经过的边改为0,使得所有边都小于当前二分的值;
3.于是问题转化为了,求树上路径交,我们可以选择树上差分。
4、第一次DFS时记录一下每个点的DFS序,因为一棵子树的DFS序是一段连续的区间,方便差分计算。
5、我们用一条边指向的点来代替它统计(当然也可以在边上计算)—每次求路径交就是在起点,终点++,LCA-=2;最后按DFS序加就好了
6、优化,我们可以在二分时记录当前值之前有没有算过,如果有,就直接return ,可以用一个数组记录这个答案,减小常数
#include<bits/stdc++.h>using namespace std;const int N = 300005;int n,m,x,y,z,tot,dfs_sort,l,r;int first[N],to[N*2],nxt[N*2],val[N*2],memery[N];int deep[N],dis[N],num[N],tmp[N],v[N],f[N][20];struct node{ int u,v,lca,len; bool operator <(const node&a)const { return len>a.len; } }c[N];inline int Readint(){ int i=0;char c; for(c=getchar();!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) i=(i<<1)+(i<<3)+c-'0'; return i;}inline void add(int x,int y,int z){ nxt[++tot]=first[x];first[x]=tot;to[tot]=y;val[tot]=z; nxt[++tot]=first[y];first[y]=tot;to[tot]=x;val[tot]=z;}inline void Dfs(int x,int fa){ num[++dfs_sort]=x;//DFS序 for(int i=1;i<=18;i++){ f[x][i]=f[f[x][i-1]][i-1]; if(!f[x][i-1]) break; } for(int i=first[x];i;i=nxt[i]){ if(to[i]==fa) continue; deep[to[i]]=deep[x]+1; dis[to[i]]=dis[x]+val[i]; v[to[i]]=val[i];//将边的值转到它指向的那个点,方便差分 f[to[i]][0]=x; Dfs(to[i],x); }}inline int lca(int a,int b){ if(deep[a]<deep[b]) swap(a,b); int k=deep[a]-deep[b]; for(int i=18;i>=0;i--) if(k&(1<<i)) a=f[a][i]; if(a==b) return a; for(int i=18;i>=0;i--) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i]; return f[a][0];}inline bool check(int x){ int cnt=0,limit=0,mx=0; memset(tmp,0,sizeof(tmp)); for(int i=1;i<=m;i++){ if(c[i].len>x){ ++tmp[c[i].u];++tmp[c[i].v];tmp[c[i].lca]-=2; limit=max(limit,c[i].len-x); cnt++; } else break;//把边从大到小排序,优化常数 } if(memery[cnt]) return memery[cnt]>=limit;//优化 if(!cnt) return true; for(int i=n;i>=1;i--) tmp[f[num[i]][0]]+=tmp[num[i]]; //计算一条边经过的次数 for(int i=2;i<=n;i++) if(tmp[i]==cnt) mx=max(mx,v[i]); memery[cnt]=mx; return memery[cnt]>=limit;}int main(){ //freopen("lx.in","r",stdin); ios::sync_with_stdio(false); cin.tie(NULL); n=Readint(),m=Readint(); for(int i=1;i<n;i++){ x=Readint(),y=Readint(); z=Readint(),add(x,y,z); r+=z; } Dfs(1,0); for(int i=1;i<=m;i++){ c[i].u=Readint(); c[i].v=Readint(); c[i].lca=lca(c[i].u,c[i].v); c[i].len=dis[c[i].u]+dis[c[i].v]-2*dis[c[i].lca]; // r=max(r,c[i].len); } sort(c+1,c+1+m); int ans=r; while(l<=r){ int mid=(l+r)>>1; if(check(mid)) ans=min(ans,mid),r=mid-1; else l=mid+1; } cout<<ans;}
阅读全文
0 0
- NOIP 2015 Day2 T3 运输计划(二分+dfs序+树上差分+倍增LCA)
- noip运输计划(倍增lca,树上差分)
- <考试题> codevs 5440 运输计划 (二分+lca+dfs序+树上差分)
- BZOJ 4326 NOIP 2015 DAY2 T3 浅谈二分及树上差分数组DFS动态统计
- 洛谷 2680[NOIP2015] 运输计划 二分+lca+树上差分+dfs序
- 【bzoj 4326】【codevs 4632】【UOJ #150】[NOIP 2015]运输计划(dfs+lca+二分答案+差分)
- 【NOIP2015】运输计划 {二分答案+倍增+树上差分}
- luogu2680【2015提高】运输计划(二分答案+lca+树上差分前缀和)
- 【BZOJ】4326 NOIP2015 运输计划 二分+LCA+树上差分
- NOIP2015 运输计划 二分答案+Tarjan LCA+树上差分
- LuoguP2680/UOJ150[NOIP2015] 运输计划 解题报告【二分答案+树上操作(LCA)+树上差分】
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- NOIP2015 运输计划 (树链剖分,LCA,树上差分)
- [BZOJ4326][NOIP2015]运输计划(二分答案+树上差分)
- bzoj 4326 运输计划 (树链剖分 + 树上差分 + 二分)
- LCA+二分+树上差分——Luogu2680 [NOIP2015]运输计划
- 【运输计划】【二分】【树上倍增】
- AndroidStudio插件管理
- 大数据任务安排第一期
- 关于数据库设计的一点心得
- TabLayout 关联了 ViewPager 下划线不见了?
- 【Spring】 (1)Aspect 自定义注解 使用该注解的地方 自动注入该注解里传的参数
- NOIP 2015 Day2 T3 运输计划(二分+dfs序+树上差分+倍增LCA)
- 开发相关的测试
- 生成mnist_model_graph.pb
- BZOJ1131 [POI2008]Sta
- 考试总结6
- 神经网络中的「注意力」是什么?怎么用?
- 不用恐惧AI的高速发展,论击败阿法狗(零)最简单的方法
- 微软 CEO 纳德拉访谈:人工智能的大方向与未来是什么?
- Sicily1798. Alice and Bob[策略问题]