1.        题目

幸福的道路(race)

【问题描述】

小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.

他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.

他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).

【输入格式】

第一行包含一个整数N.

第二至第N行,每行两个数字Fi , Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.

【输出格式】

每天的锻炼路径长度

【样例输入】

3

1 1

1 3

【样例输出】

3

4

4

数据范围:

50%的数据N<=1000

80%的数据N<=100 000

100%的数据N<=1000 000

2.        算法

第一种方法:用队列优化的树形动规。

还有一种比较纠结的,以前在博客中写过:

首先说明一个定理,离树中某一个点最远的点,一定是在树的直径(树中距离最远的两个点之间的路径)的一个端点。

证明:如果存在一个更远的点,不是端点,但是比较远的那个端点距离这个点更远,则此时,距离这个点较近的那个端点可以经过这个点,到达那个更远的点,这样就会找出一条比直径更长的路径。但事实上,直径应该是一个树中最长的路径,所以离树中某一个点最远的点,一定是在树的直径(树中距离最远的两个点之间的路径)的一个端点,证毕。

然后,这样的话,就可以先求出树的直径的两个端点(从任意一个点开始  BFS ,找到距离他最远的那个点,根据上方定理,这必是一个端点,再从这个已知端点开始 BFS ,找到距离他最远的那个点,显然这就是另一个端点),然后从这两个点开始,走单源最短路。然后求解的时候,只需要找出每一个点距这两个点的距离中的较大的那个,就是答案了。

然后这个题的标准算法是树形动规。

这个方法太麻烦,而且这是个多叉树,存都不好存,本人没有深入研究,在此引用一下。

1.题目可以使用搜索做,但是由于数据范围极大,极可能会超时

2.这样就可以向其他方面思考:题目中给出的是一棵树,就是树形DP吧

距离一个节点最远的点  在此节点的子树中 或 在它的父节点的其他子树中

这样,每一个节点要存储三个信息:

1.在他的子树中离他最远的点到他的距离

2.在他的子树中离他第二远的点到他的距离

3.在他的祖先及其出了他本身的子树中里他最远的点到他的距离

假设F[i][0]是在以i为根的子树的点里离i最远的距离

F[i][2]是不在以i为根的子树的点离i最远的距离

显然答案是max(F[i][0] , F[i][2])

第一种显然一次dfs就搞定了

而第二个不是很好办..

所以我们分析一下..得到了这个方程

F[i][2] = max(F[Parent[i]][2] , F[Parent[i]][0]) + Dist[Parent[i]][i];

不过显然当如果F[Parent[i]][0]的决策是i的时候是错的..所以我们只要再记

录一个“在以i为根的子树里且第一步决策和F[i][0]不同的点离i的最大值”令其为F[i][1]

if(F[Parent[i]][0] == F[i][0] + Dist[Parent[i]][i])

F[i][2] = max(F[Parent[i]][2] , F[Parent[i]][1]) + Dist[Parent[i]][i];

Else F[i][2] = max(F[Parent[i]][2] , F[Parent[i]][0]) + Dist[Parent[i]][i];

4.        代码

特殊算法 (Leve)

type pointer=^rec;

rec=record

num,len:longint;

next:pointer;

end;

var

i,j,a1,a2,n,x,y,max:longint;

link:array[1..10000] of pointer;

d1,d2:array[1..10000] of longint;

v:array[1..10000] of boolean;

q:array[1..1000000] of longint;

p:pointer;

procedure spfa1(x:longint);

var

i,l,r,temp:longint;

p:pointer;

begin

filldword(d1,sizeof(d1)>>2,maxlongint>>1);

fillchar(v,sizeof(v),false);

d1[x]:=0;

v[x]:=true;

q[1]:=x;

l:=0; r:=1;

while l<r do

begin

inc(l);

temp:=q[l];

p:=link[temp];

v[temp]:=false;

while p<>nil do

begin

if d1[p^.num]>d1[temp]+p^.len then

begin

d1[p^.num]:=d1[temp]+p^.len;

if not v[p^.num] then

begin

v[p^.num]:=true;

inc(r);

q[r]:=p^.num;

end;

end;

p:=p^.next;

end;

end;

end;

procedure spfa2(x:longint);

var

i,l,r,temp:longint;

p:pointer;

begin

filldword(d2,sizeof(d2)>>2,maxlongint>>1);

fillchar(v,sizeof(v),false);

d2[x]:=0;

v[x]:=true;

q[1]:=x;

l:=0; r:=1;

while l<r do

begin

inc(l);

temp:=q[l];

p:=link[temp];

v[temp]:=false;

while p<>nil do

begin

if d2[p^.num]>d2[temp]+p^.len then

begin

d2[p^.num]:=d2[temp]+p^.len;

if not v[p^.num] then

begin

v[p^.num]:=true;

inc(r);

q[r]:=p^.num;

end;

end;

p:=p^.next;

end;

end;

end;

begin

assign(input,'length.in');

assign(output,'length.out');

reset(input);

rewrite(output);

readln(n);

for i:=2 to n do

begin

read(x,y);

new(p);

p^.num:=x;

p^.len:=y;

p^.next:=link[i];

link[i]:=p;

new(p);

p^.num:=i;

p^.len:=y;

p^.next:=link[x];

link[x]:=p;

end;

spfa1(1);

max:=0;

for i:=1 to n do

if d1[i]<maxlongint>>1 then

if d1[i]>max then

begin

max:=d1[i];

a1:=i;

end;

spfa1(a1);

max:=0;

for i:=1 to n do

if d1[i]<maxlongint>>1 then

if d1[i]>max then

begin

max:=d1[i];

a2:=i;

end;

spfa2(a2);

for i:=1 to n do

begin

if d1[i]=maxlongint>>1 then d1[i]:=0;

if d2[i]=maxlongint>>1 then d2[i]:=0;

end;

for i:=1 to n do

if d1[i]>d2[i] then

writeln(d1[i])

else

writeln(d2[i]);

close(input);

close(output);

end.

树形动规 (std)

program length;

type

edge=record

x,w,next:longint;

end;

var

e,e2:array[0..200000]of edge;

k,k2:array[0..10000]of longint;

fa:array[0..10000]of longint;

w:array[0..10000]of longint;

tot,tot2,i,j,n,x,y:longint;

v:array[0..10000]of boolean;

f:array[0..10000,0..2]of longint;

function max(a,b:longint):longint;

begin

if (a>b) then exit(a) else exit(b);

end;

procedure add2(a,b,c:longint);

begin

inc(tot2);

e2[tot2].x:=b;

e2[tot2].w:=c;

e2[tot2].next:=k2[a];

k2[a]:=tot2;

end;

procedure add(a,b,c:longint);

begin

inc(tot);

e[tot].x:=b;

e[tot].w:=c;

e[tot].next:=k[a];

k[a]:=tot;

end;

procedure build(x:longint);

var

t:longint;

begin

v[x]:=true;

t:=k2[x];

while (t<>0) do

begin

if (not v[e2[t].x]) then

begin

fa[e2[t].x]:=x;

w[e2[t].x]:=e2[t].w;

add(x,e2[t].x,e2[t].w);

build(e2[t].x);

end;

t:=e2[t].next;

end;

end;

procedure dp_down(x:longint);

var

t:longint;

begin

t:=k[x];

while (t<>0) do

begin

dp_down(e[t].x);

if (f[e[t].x][1]+e[t].w>f[x][1]) then

begin

f[x][2]:=f[x][1];

f[x][1]:=f[e[t].x][1]+e[t].w;

end

else

if (f[e[t].x][1]+e[t].w>f[x][2]) then

begin

f[x][2]:=f[e[t].x][1]+e[t].w;

end;

t:=e[t].next;

end;

end;

procedure dp_up(x:longint);

var

t:longint;

begin

if (fa[x]<>0) then

begin

if (f[fa[x]][1]=f[x][1]+w[x]) then

f[x][0]:=max(f[fa[x]][2],f[fa[x]][0])+w[x]

else f[x][0]:=max(f[fa[x]][1],f[fa[x]][0])+w[x];

end;

t:=k[x];

while (t<>0) do

begin

dp_up(e[t].x);

t:=e[t].next;

end;

end;

begin

assign(input,'length.in');reset(input);

assign(output,'length.out');rewrite(output);

readln(n);

for i:=2 to n do

begin

readln(x,y);

add2(i,x,y);

add2(x,i,y);

end;

build(1);

dp_down(1);

dp_up(1);

for i:=1 to n do

begin

writeln(max(f[i][0],f[i][1]));

end;

close(input);

close(output);

end.

PS:这是这个题的化简版,原题:

【问题描述】

小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.

他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.

他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).

他们不愿再经历之前的大起大落,所以决定连续几天的幸福值波动不能超过M(即一段连续的区间并且区间的最大值最小值之差不超过M).他们想知道要是这样的话他们最多能连续锻炼多少天(hint:不一定从第一天一直开始连续锻炼)?

现在,他们把这个艰巨的任务交给你了!

【输入格式】

第一行包含两个整数N, M(M<=10^9).

第二至第N行,每行两个数字Fi , Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.

【输出格式】

最长的连续锻炼天数

【样例输入】

3 2

1 1

1 3

【样例输出】

3

数据范围:

50%的数据N<=1000

80%的数据N<=100000

100%的数据N<=1000 000

然后,求出来每天锻炼路径之后,最长连续锻炼天数怎么快速的求出来。。。。才疏学浅,三个点超时。

这是那个 70 的代码。。。。写得好烂。。。。

代码:(SueMiller)

program ACRush;
var a:array[0..2000010,1..3]of longint;
    dist1,dist2,dist3:array[0..1000010]of longint;
    t,arr:array[0..1000010]of longint;
    q:array[0..10000010]of longint;
    vq:array[0..1000010]of boolean;
    i,j,k,d1,d2:longint;
    n,m,tot,maxx,minn,l,r,ans,tempn,tempx:longint;

procedure quicksort(l,r:longint);
var x,i,j:longint;
begin
 i:=l; j:=r; x:=a[(l+r)>>1,1];
 repeat
  while a[i,1]<x do inc(i);
  while x<a[j,1] do dec(j);
  if i<=j then
   begin
   a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0];
   inc(i); dec(j);
   end;
 until i>j;
 if l<j then quicksort(l,j);
 if i<r then quicksort(i,r);
end;

procedure spfa1(x:longint);
begin
  l:=0;
  r:=1;
  q[1]:=x;
  filldword(dist1,sizeof(dist1)>>2,maxlongint>>1);
  dist1[x]:=0;
  fillchar(vq,sizeof(vq),false);
  vq[x]:=true;
  while l<r do
    begin
      inc(l);
      for i:=t[q[l]] to tot do
        if a[i,1]<>q[l] then break
        else
          begin
            if dist1[q[l]]+a[i,3]<dist1[a[i,2]] then
              begin
                dist1[a[i,2]]:=dist1[q[l]]+a[i,3];
                if not vq[a[i,2]] then
                  begin
                    inc(r);
                    q[r]:=a[i,2];
                    vq[a[i,2]]:=true;
                  end;
              end;
          end;

vq[q[l]]:=false;
    end;
end;

procedure spfa2(x:longint);
begin
  l:=0;
  r:=1;
  q[1]:=x;
  filldword(dist2,sizeof(dist2)>>2,maxlongint>>1);
  dist2[x]:=0;
  fillchar(vq,sizeof(vq),false);
  vq[x]:=true;
  while l<r do
    begin
      inc(l);
      for i:=t[q[l]] to tot do
        if a[i,1]<>q[l] then break
        else
          begin
            if dist2[q[l]]+a[i,3]<dist2[a[i,2]] then
              begin
                dist2[a[i,2]]:=dist2[q[l]]+a[i,3];
                if not vq[a[i,2]] then
                  begin
                    inc(r);
                    q[r]:=a[i,2];
                    vq[a[i,2]]:=true;
                  end;
              end;
          end;

vq[q[l]]:=false;
    end;
end;

procedure spfa3(x:longint);
begin
  l:=0;
  r:=1;
  q[1]:=x;
  filldword(dist3,sizeof(dist3)>>2,maxlongint>>1);
  dist3[x]:=0;
  fillchar(vq,sizeof(vq),false);
  vq[x]:=true;
  while l<r do
    begin
      inc(l);
      for i:=t[q[l]] to tot do
        if a[i,1]<>q[l] then break
        else
          begin
            if dist3[q[l]]+a[i,3]<dist3[a[i,2]] then
              begin
                dist3[a[i,2]]:=dist3[q[l]]+a[i,3];
                if not vq[a[i,2]] then
                  begin
                    inc(r);
                    q[r]:=a[i,2];
                    vq[a[i,2]]:=true;
                  end;
              end;
          end;

vq[q[l]]:=false;
    end;
end;

function max(x,y:longint):longint;
begin
  if x>y then exit(x) else exit(y);
end;

begin
  assign(input,'race.in');reset(input);
  assign(output,'race.out');rewrite(output);

readln(n,m);
  for i:=1 to n-1 do
    begin
      readln(j,k);
      inc(tot);
      a[tot,1]:=i+1;
      a[tot,2]:=j;
      a[tot,3]:=k;
      inc(tot);
      a[tot,1]:=j;
      a[tot,2]:=i+1;
      a[tot,3]:=k;
    end;

quicksort(1,tot);
  t[a[1,1]]:=1;
  for i:=2 to tot do
    if a[i,1]<>a[i-1,1] then t[a[i,1]]:=i;

spfa1(1);

d1:=0;
  k:=0;
  for i:=1 to n do
    if dist1[i]>k then
      begin
        k:=dist1[i];
        d1:=i;
      end;

spfa2(d1);

d2:=0;
  k:=0;
  for i:=1 to n do
    if dist2[i]>k then
      begin
        k:=dist2[i];
        d2:=i;
      end;
  spfa3(d2);

for i:=1 to n do
    arr[i]:=max(dist2[i],dist3[i]);

ans:=1;
  for i:=1 to n do
    begin
      l:=i;
      r:=i;
      maxx:=arr[i];
      minn:=arr[i];
      tempn:=arr[i]+1;
      tempx:=arr[i]-1;
      while maxx-minn<=m do
        begin
          dec(l);
          if l=0 then break;
          if arr[l]<minn then
            begin
              tempn:=minn;
              minn:=arr[l];
            end
          else
            if arr[l]<tempn then tempn:=arr[l];
          if arr[l]>maxx then
            begin
              tempx:=maxx;
              maxx:=arr[l];
            end
          else
            if arr[l]>tempx then tempx:=arr[l];
        end;
      if l<>0 then
        begin
          if arr[l]=maxx then maxx:=tempx;
          if arr[l]=minn then minn:=tempn;
        end;
      inc(l);
      while maxx-minn<=m do
        begin
          inc(r);
          if r>n then break;
          if arr[r]<minn then
            begin
              tempn:=minn;
              minn:=arr[r];
            end
          else
            if arr[r]<tempn then tempn:=arr[r];
          if arr[r]>maxx then
            begin
              tempx:=maxx;
              maxx:=arr[r];
            end
          else
            if arr[r]>tempx then tempx:=arr[r];
        end;
      if r<>n+1 then
        begin
          if arr[r]=maxx then maxx:=tempx;
          if arr[r]=minn then minn:=tempn;
        end;
      dec(r);
      if r-l+1>ans then ans:=r-l+1;
      if ans=n then break;

l:=i;
      r:=i;
      maxx:=arr[i];
      minn:=arr[i];
      tempn:=arr[i]+1;
      tempx:=arr[i]-1;
      while maxx-minn<=m do
        begin
          inc(r);
          if r>n then break;
          if arr[r]<minn then
            begin
              tempn:=minn;
              minn:=arr[r];
            end
          else
            if arr[r]<tempn then tempn:=arr[r];
          if arr[r]>maxx then
            begin
              tempx:=maxx;
              maxx:=arr[r];
            end
          else
            if arr[r]>tempx then tempx:=arr[r];
        end;
      if r<>n+1 then
        begin
          if arr[r]=maxx then maxx:=tempx;
          if arr[r]=minn then minn:=tempn;
        end;
      dec(r);
      while maxx-minn<=m do
        begin
          dec(l);
          if l=0 then break;
          if arr[l]<minn then
            begin
              tempn:=minn;
              minn:=arr[l];
            end
          else
            if arr[l]<tempn then tempn:=arr[l];
          if arr[l]>maxx then
            begin
              tempx:=maxx;
              maxx:=arr[l];
            end
          else
            if arr[l]>tempx then tempx:=arr[l];
        end;
      if l<>0 then
        begin
          if arr[l]=maxx then maxx:=tempx;
          if arr[l]=minn then minn:=tempn;
        end;
      inc(l);
      if r-l+1>ans then ans:=r-l+1;
      if ans=n then break;
    end;

writeln(ans);

close(input);close(output);
end.

转载于:https://www.cnblogs.com/SueMiller/archive/2011/10/15/2213442.html

解题报告 幸福的道路相关推荐

  1. 程序设计算法竞赛高级——练习1解题报告

    程序设计算法竞赛高级--练习1解题报告 1001 寒冰王座 Problem Description 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的 ...

  2. 解题报告:线性规划与网络流24题

    目录 A.飞行员配对方案问题 (二分图最大匹配)(最大流)[提高+/省选- ] B.太空飞行计划问题(最大权闭合图转最小割.最小割方案输出)[省选/NOI- ] C.最小路径覆盖问题(有向无环图最小路 ...

  3. 《商务旅行》解题报告

    <商务旅行>解题报告 by mps [题目描述] 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其 ...

  4. NOIP2012普及组 (四年后的)解题报告 -SilverN

    本章施工仍未完成 现在的时间是3.17 0:28,我困得要死 本来今天(昨天?)晚上的计划是把整个四道题的题解写出来,但是到现在还没写完T4的高效算法,简直悲伤. 尝试了用floyd写T4,终于大功告 ...

  5. 久久未至的Codevs1024一塔湖图解题报告

    一直想给这个题写个解题报告但是给忘了OTZ难产了这么久终于出来了 这个题当时坑了我一个星期整,所以一定要写一个解题报告纪念一下 1024 一塔湖图 时间限制: 1 s 空间限制: 128000 KB ...

  6. SHU 第十届程序设计联赛(夏季赛) 解题报告

    Problem A: 一日三餐开销 水题,基本上都过了,直接贴代码: 1 #include <iostream> 2 #include <cstdio> 3 using nam ...

  7. CF144D Missile Silos 解题报告 *

    CF144D Missile Silos 解题报告 1 题目链接 https://codeforces.com/problemset/problem/144/D 2 题目整理 题目 : 导弹发射井 题 ...

  8. uscao 线段树成段更新操作及Lazy思想(POJ3468解题报告)

    线段树成段更新操作及Lazy思想(POJ3468解题报告) 标签: treequerybuildn2cstruct 2011-11-03 20:37 5756人阅读 评论(0) 收藏 举报  分类: ...

  9. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

最新文章

  1. MyBatis中#{}和${}的区别
  2. cuda 核函数 for循环_【CUDA 基础】6.2 并发内核执行
  3. 深度学习(十四)基于CNN的性别、年龄识别
  4. 基于ssm的水果商城系统项目总结
  5. 单片机音频谱曲软件_【自己写的小软件】CLY单片机音乐代码超级生成器
  6. SQLi LABS Less-6 报错注入+布尔盲注
  7. js调用数科阅读器_多种方式实现JS调用后台方法进行数据交互
  8. 数据结构导论【五】之 图
  9. 数字证书:签名证书加密证书
  10. 第一个任务摧毁广播的_第一个完全在Linux上广播的广播
  11. 模拟购物车系统(添加、修改、查询、结算)(Java实现)
  12. Fantastic-Matplotlib 第二回
  13. 2022年国家高新技术企业认定评审最新标准及补贴政策重点,补贴10-50万
  14. 使用JMeter的Java Sampler轻松定制自己的benchmark
  15. 视频教程-数据挖掘基础:零基础学Python数据分析-大数据
  16. 「合规」震惊!地图可视化竟能如此玩,零门槛,全免费,效果远胜主流作图工具!...
  17. 股票知识:成本价的计算
  18. 如何把软件上传服务器别人能下载呢
  19. 通关kafka之Kafka面试题
  20. SSM+Vue+Element-UI实现员工工资管理系统

热门文章

  1. week08 S8-01 docker images tensorflow-jupyter
  2. 命令行管理windows服务器角色
  3. asp.net中日志框架Log4Net的使用
  4. pb 数据窗口下拉表
  5. Android 简介:Android SDK 和开发框架简介
  6. Andriod开发前准备
  7. phpeclipse+xdebug配置
  8. 实现APP-V服务全程跟踪(二)
  9. 利用 caffe的 python接口测试训练好的 mnist 模型
  10. 单选框加了css后显示不出来,layui radio 单选框 效果 显示不来 解决方法