题意:求树上的一条费用不超过m的路径,使得总长度尽量大。

人参第一发树分治,紫书上思路讲得比较清晰,这里不再赘述。

实现的时候,用一个类似时间戟的东西,记录结点首次访问的时间,并保存结点序列。

合并的时候用map组织有序表。和Defense Lines类似

复杂度O(nlog^2n)

#include<bits/stdc++.h>
using namespace std; const int maxn = 3e4+;
int n,m;
int hd[maxn], nx[maxn<<], to[maxn<<], dam[maxn<<], len[maxn<<], ec; inline void add(int u,int v,int D,int L)
{
to[ec] = v;
dam[ec] = D;
len[ec] = L;
nx[ec] = hd[u];
hd[u] = ec++;
} int root, best;
int ct[maxn];
//best = n
void GetBaryCenter(int u,int f)
{
ct[u] = ;
int Mx = ;
for(int i = hd[u]; ~i; i = nx[i]){
if(to[i] != f){
GetBaryCenter(to[i], u);
ct[u] += ct[to[i]];
Mx = max(Mx,ct[to[i]]);
}
}
Mx = max(Mx,n-ct[u]);
if(Mx < best){
best = Mx;
root = u;
}
} #define MP make_pair
#define fi first
#define se second
int C[maxn], L[maxn]; map<int,int> mp;
map<int,int>::iterator it; int ans;
int path[maxn];
int pre[maxn], dfs_clk;
//dfs_clk = 0, ans = 0;
void dfs(int u = root,int f = )
{
path[dfs_clk] = u;
pre[u] = dfs_clk++;
C[u] = ; L[u] = ;
for(int i = hd[u]; ~i; i = nx[i]){
if(to[i] != f){
int v = to[i];
dfs(v,u);
for(int j = pre[v]; j < dfs_clk ; j++){
int x = path[j];
C[x] += dam[i];
L[x] += len[i];
}
}
}
//子树都访问完里以后统一处理以保证互不干扰,这样mp就可以设置为全局变量
mp.clear();
for(int i = hd[u]; ~i; i = nx[i]){
int nex = nx[i];
int lim = ~nex? pre[to[nex]] : dfs_clk;
if(to[i] != f){
int v = to[i];
for(int j = pre[v]; j < lim ; j++){
int x = path[j];
if(C[x] <= m){
ans = max(ans,L[x]);
it = mp.upper_bound(m-C[x]);//找到一个key <= C[x]
if(it != mp.begin()){
ans = max(ans,(--it)->second+L[x]);
}
}
}
for(int j = pre[v]; j < lim ; j++){
int x = path[j];
if(C[x] <= m){
it = mp.lower_bound(C[x]);
bool swc = false;
if(it == mp.begin() || (swc = true , L[x] > (--it)->se) ){
if(swc) it++;
while(it != mp.end() && it->se <= L[x]) mp.erase(it++);
if(it == mp.end() || it->fi > C[x]) {//lower_bound可能使得it指向key == C[x] 而 val >= L[x]
mp.insert(MP(C[x],L[x]));
}
}
}
}
}
}
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int T, ks = ; cin>>T;
while(T--){
scanf("%d%d",&n,&m);
memset(hd+,-,sizeof(int)*n); ec = ;
for(int i = n; --i;){
int a,b,D,L; scanf("%d%d%d%d",&a,&b,&D,&L);
add(a,b,D,L); add(b,a,D,L);
}
best = n+;
GetBaryCenter(,);
dfs_clk = ans = ;
dfs();
printf("Case %d: %d\n",++ks,ans);
}
return ;
}

最新文章

  1. Unity3D 与android交互流程步骤
  2. 浅谈Linux中的信号处理机制(三)
  3. 【后台测试】Linux下小试jmeter
  4. mysql时间类型在iBATIS框架下的问题(原创哦)
  5. 317. Shortest Distance from All Buildings
  6. Android include和merge标签的使用
  7. MVC小系列(十一)【Html.BeginForm与Ajax.BeginForm】
  8. XSS初体验
  9. [python语法巩固][leetcode326][Power of Three]
  10. 【转】 利用spring的profile切换不同的环境
  11. COM编程-注册DLL形式的COM服务器
  12. Linux下*.tar.gz/.tar.bz2 文件解压缩安装命令
  13. BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆
  14. Linux内存管理 (16)内存规整
  15. resources中添加配置文件
  16. JsonServer服务环境搭建
  17. 并查集---java模板
  18. if else if else 语句
  19. 启明星系统安装教程(如何在windows2012里配置IIS)
  20. [daily][gnucash] 复式记账

热门文章

  1. linux---安装ftp并配置用户部分权限
  2. PHP5 $this self parent static的区别
  3. hdu2586(lca模板 / tarjan离线 + RMQ在线)
  4. express-http-proxy 的基础使用
  5. OnclickListener
  6. python实现王者荣耀英图片收集
  7. .netcore中无法使用System.Drawing --解决方案
  8. java 使用 spirng 监控 cpu 使用 状态。。。。
  9. mysql隔离级别与锁,接口并发响应速度的关系(2)
  10. windows下显示隐藏的文件