NOIP2015提高组——运输计划(transport)
来源:互联网 发布:苹果mac如何装虚拟机 编辑:程序博客网 时间:2024/06/11 03:24
题目链接
题意:给定一棵有n个节点的树(带有边权),再给定m条树中的路径。允许将一条树边的权改为0,并使得这些路径的最长距离最小。输出该修改方案中这些路径中最长的一条。
(n,m<=300000)
分析:
要求最大值最小,首先想到的是二分答案,即二分最终这些路径的长度中最长的一条,设为k,然后再判断是否可以做到。那么该如何判断可行性呢?
如果某一路径的距离大于k,那么显然需要修改的边是这条路径中的某条边。那么,就可以先将这些路径标记起来,然后要找出一条这些路径都覆盖边,如果有某一条边能满足,即该边的权值>=最长路径-答案k,那么这个方案是可行的。
还有一个问题,怎样找出这些边?如果树退化成一条链,其实就是求某点有多少个区间覆盖,用差分即可。那么,树上差分!
对于所有的路径i,设两头分别为a[i]与b[i],l[i]=LCA(s[i],t[i]),则预处理时f[a[i]]++,f[b[i]++],f[l[i]]-=2;按dfs序的倒序来做,每次将自己的f[i]加到父亲的f[i],这样就可以统计了。
最后一个问题,数据比较大,一定要注意常数优化(下面是建议):
1,将用vector存的邻接表改成链式前向星,
2,输入优化(getchar)
3,可以使用Tarjan算法来求LCA
4,二分的时候可将初始范围尽量缩小。
【程序(使用的是倍增算法求LCA)(时间复杂度O(nlogn))】
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cstdlib>#include <cmath>#include <vector>#include <queue>using namespace std;#define N 300010#define logN 24#define INF 0x3fffffffvoid read(int &t){ char ch; while(ch = getchar()) if(ch>='0' && ch<='9') break; t = ch - '0'; while(ch = getchar()) if(ch>='0' && ch<='9') t = (t<<3)+(t<<1)+ch-'0'; else break;}struct Edge{ int to; int val; int next;};Edge edge[N<<1];int head[N];int cnt;void AddEdge(int u,int v,int val){ edge[cnt].val = val; edge[cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt++;}int p[N],dis[N],dep[N],gra[N][logN],topre[N];void dfs(int u,int pre){ p[++cnt] = u; for(int i=1;i<logN;i++) { gra[u][i] = gra[gra[u][i-1]][i-1]; if(!gra[u][i]) break; } for(int i = head[u];~i;i = edge[i].next) { int v = edge[i].to; if(pre == v) continue; dis[v] = dis[u] + edge[i].val; dep[v] = dep[u] + 1; gra[v][0] = u; topre[v] = edge[i].val; dfs(v,u); }}int LCA(int x,int y){ if(dep[x]>dep[y]) swap(x,y); for(int i = logN-1;i>=0;i--) if(dep[gra[y][i]] >= dep[x]) y = gra[y][i]; for(int i = logN-1;i>=0;i--) if(gra[y][i] != gra[x][i]) { x = gra[x][i]; y = gra[y][i]; } if(x != y) x = gra[x][0]; return x;}int n,m,Maxx,Minn;int f[N],a[N],b[N],l[N],d[N];bool check(int k){ memset(f,0,sizeof(f)); cnt = 0; for(int i=1;i<=m;i++) if(d[i] > k) { f[a[i]]++; f[b[i]]++; f[l[i]] -= 2; cnt++; } for(int i=n;i>=1;i--) { f[gra[p[i]][0]] += f[p[i]]; if(topre[p[i]] >= Maxx - k && f[p[i]] == cnt) return true; } return false;}int Binary_Search(int l,int r){ int mid; while(l < r) { mid = (l+r)>>1; if(check(mid)) r = mid; else l = mid+1; } return l;}int main(){ read(n); read(m); memset(head,-1,sizeof(head)); int x,y,z,Max1; Max1 = 0; for(int i=1;i<n;i++) { read(x); read(y); read(z); AddEdge(x,y,z); AddEdge(y,x,z); Max1 = max(Max1,z); } cnt = 0; dep[1] = 1; dep[0] = -1; dfs(1,0); for(int i=1;i<=m;i++) { read(a[i]); read(b[i]); l[i] = LCA(a[i],b[i]); d[i] = dis[a[i]] + dis[b[i]] - (dis[l[i]] << 1); Maxx = max(Maxx,d[i]); } printf("%d\n",Binary_Search(Maxx - Max1,Maxx+1)); return 0;}
阅读全文
0 0
- NOIP2015提高组——运输计划(transport)
- NOIP2015复赛提高组之运输计划
- bzoj 4326 && Noip2015提高组运输计划
- 【uoj150】 NOIP2015—运输计划
- C++——NOIP2015提高组day2 t3——运输计划
- {题解}[jzoj4328]NOIP2015提高组Day2 运输计划
- [二分+差分]BZOJ 4326——NOIP2015 运输计划
- 【NOIP2015】【BZOJ4326】运输计划
- [bzoj4326][NOIP2015]运输计划
- NOIP2015 运输计划
- NOIP2015 day2t3 运输计划
- NOIP2015运输计划 题解
- noip2015 运输计划
- codevs4632: [NOIP2015]运输计划
- NOIP2015 D2T3运输计划
- noip2015运输计划
- 【NOIP2015】Day2T3 运输计划
- NOIP2015运输计划
- linux端口操作
- float与double的范围和精度
- 欢迎使用CSDN-markdown编辑器
- 强类型 JavaScript 的解决方案
- elasticsearch异常Elasticsearch requires at least Java 8 but your Java XXXXX
- NOIP2015提高组——运输计划(transport)
- javaee的几个元注解
- 数据转换函数
- (算法分析Week8)Best Time to Buy and Sell Stock[Easy]
- C/C++ 中的0长数组(柔性数组)
- Python lambda 表达式
- java序列化和数据库设计
- Excel 时间差 小时小数 日期对应星期
- es6环境搭建(2)创建js编译任务。