【NOIP2015】【bzoj4326】【uoj146】运输计划 ——O(n*log)算法
来源:互联网 发布:java json格式 编辑:程序博客网 时间:2024/05/21 22:57
最大数据是n,m=300000,所以应该试着把时间压在n*log(xxx)以内 //在本算法下,xxx=n*∑ti
考虑修改一条边后,所有长度大于答案的路径都被缩短,因此二分答案
设二分到的答案为k
那么被删掉的边一定是所有长于k的路径的公共边之一,因此问题转化为,在O(m)时间内求出m条路径的交集中的最长边
首先,可以在O(1)时间内求出两条路径的交集:对于路径s-t 和 s'-t' 分别求出s'到s-t上最近点u,t'到s-t上最近点v,那么交集就是(u,v)
这里若无解,交集会变成s-t上一个点,结束时特判即可。在其他题目中求路径交集需要再反向求一次,在此不详细解释。
求最近点代码如下
int closest(int x,int s,int t){ int r=lca(s,t); if(lca(x,r)!=r) return r; int p=lca(x,s); return p==r?lca(x,t):p;}
大致思路是,若最近点不是s和t 的公共祖先,那么判断是s那侧还是t那侧
其中lca要转化为RMQ,方可O(1)实现
找到交集后,从两个顶点开始逐条边向父节点移动,直到撞上就可以了,效率很低,O(n)但不会影响整体复杂度
代码:
#include<cstdio>#include<algorithm>#include<cstring>#include<vector>using namespace std;#define maxm 300005#define maxn 300005#define maxt 600005#define lca(u,v) rmq(pre[u],pre[v])#define mid (l+r)/2int n,m;struct edge{ int v; int w; int next; edge(int v,int w,int next):v(v),w(w),next(next){} edge(){}}e[maxn*2];int newedge,dfsclock;int ind[maxn];void addedge(int u,int v,int l){ e[++newedge]=edge(v,l,ind[u]); ind[u]=newedge;}int f[maxn];int pre[maxn];int dis[maxn],dep[maxn];int visiting[maxt];int st[maxt][20];int log[maxt];void dfs(int u,int fa){ f[u]=fa; dep[u]=dep[fa]+1; pre[u]=++dfsclock; visiting[dfsclock]=u; for(int i=ind[u];i;i=e[i].next) { int v=e[i].v; if(v!=fa) { dis[v]=dis[u]+e[i].w; dfs(v,u); visiting[++dfsclock]=u; } }}void rmq_init(){ log[1]=0; for(int i=2;i<=dfsclock;i++) log[i]=log[i>>1]+1; dep[0]=0x7fffffff; for(int i=1;i<=dfsclock;i++) st[i][0]=visiting[i]; for(int l=1,t=0;l<=dfsclock;l<<=1,t++) for(int i=1;i+l<=dfsclock;i++) st[i][t+1]=dep[st[i][t]]<dep[st[i+l][t]]?st[i][t]:st[i+l][t];}int rmq(int l,int r){ if(l>r) swap(l,r); int k=log[r-l+1]; int a=st[l][k],b=st[r-(1<<k)+1][k]; return dep[a]<dep[b]?a:b;}int closest(int x,int s,int t){ int r=lca(s,t); if(lca(x,r)!=r) return r; int p=lca(x,s); return p==r?lca(x,t):p;}struct mission{ int s,t; int l; void input() { scanf("%d%d",&s,&t); l=dis[s]+dis[t]-2*dis[lca(s,t)]; }}q[maxm];int ln[maxm];bool operator <(mission a,mission b){ return a.l<b.l;}bool judge(int x){ int p=upper_bound(ln+1,ln+m+1,x)-ln; if(p==m+1) return true; int ss=q[p].s,tt=q[p].t; int maxlen=0; for(int i=p+1;i<=m;i++) { ss=closest(q[i].s,q[i].t,ss); tt=closest(q[i].s,q[i].t,tt); } if(ss==tt) return false; while(ss!=tt) { int &a=dep[ss]>dep[tt]?ss:tt; maxlen=max(maxlen,dis[a]-dis[f[a]]); a=f[a]; } if(ln[m]-maxlen<=x) return true; else return false;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { int a,b,t; scanf("%d%d%d",&a,&b,&t); addedge(a,b,t); addedge(b,a,t); } dfs(1,0); rmq_init(); for(int i=1;i<=m;i++) q[i].input(); sort(q+1,q+m+1); for(int i=1;i<=m;i++) ln[i]=q[i].l; int l=0,r=0x7fffffff; while(l<r) { if(judge(mid)) r=mid; else l=mid+1; } printf("%d",l);}
0 0
- 【NOIP2015】【bzoj4326】【uoj146】运输计划 ——O(n*log)算法
- 【NOIP2015】【BZOJ4326】运输计划
- [bzoj4326][NOIP2015]运输计划
- [bzoj4326]NOIP2015 运输计划
- bzoj4326 NOIP2015 运输计划
- bzoj4326: NOIP2015 运输计划
- [bzoj4326][NOIP2015] 运输计划 差分+LCA
- bzoj4326: NOIP2015 运输计划(lca+二分)
- 【uoj150】 NOIP2015—运输计划
- 【BZOJ4326】NOIP2015 运输计划【LCA】【路径求并】
- [BZOJ4326][NOIP2015][倍增][二分][差分序列]运输计划
- 【NOIP2015】【bzoj4326】运输计划 LCA+差分+二分答案
- [BZOJ4326][NOIP2015]运输计划(二分答案+树上差分)
- 【二分+LCA+差分】BZOJ4326(NOIP2015)[运输计划]题解
- BZOJ4326(NOIP2015)运输计划--二分+LCA+差分
- bzoj4326 & UOJ150【NOIP2015】运输计划 ( 树上差分 + lca )
- 洛谷P2680 运输计划(NOIp2015)(BZOJ4326)
- 【Bzoj4326】运输计划
- MyBatis复习(2)
- angularJs-UI-bootstrap系列教程1(使用前的准备)
- JAVA中的三目运算符
- Android 开发知识点汇总
- T-SQL中保留的关键字
- 【NOIP2015】【bzoj4326】【uoj146】运输计划 ——O(n*log)算法
- 11-8
- HarborRegistry——centos中设置Harbor Registry的https
- 21. Merge Two Sorted Lists
- 一些你需要知道的布局优化技巧
- 在centos7.0下安装xtrabackup报错
- 描述Eval和Bind的区别
- 前端面试题总结--1 JS篇
- jquery操作iframe的方法:父页面和子页面相互操作的方法