素材采集 良心题解

素材采集

 

Description

拿着照相机在幻想乡上空拍摄取材是射命丸文的日常工作。由于没有定期给灵梦提供魔理沙的照片,她被规定只能沿一定的空路飞行。为了方便管理,幻想乡的空路是这样建立的:一开始有三个景点,它们之间互相由空路相连。之后景点被一个一个加入,每个景点都恰好跟已加入的并且有空路相连的两个景点相连。她可以从任何一个景点开始,沿着空路飞行,并且每到一个景点都拍下此处少女的私密照片,最后还要回到一开始的景点。由于拍照太多会引起少女公愤从而被间隙,除了开始的景点要经过两次之外每个景点最多只能经过一次。文文想知道最多能在多少景点取材。

 

Input format

第一行一个数n,代表景点个数。一开始的景点编号为1,2,3,接下来景点的编号按加入的时间顺序依次递增。

接下来n-3行,第i行有两个整数代表第i+3号景点所连接的两个景点编号。

Output format

一个数,最多的景点个数。

 

Sample input

5

1 2

2 1

 

Sample output

4

 

Range&Others

20%的数据满足:4n10

30%的数据满足:4n15

50%的数据满足:4n1000

100%的数据满足:4n100000

 

 

题目应该很好理解吧=w=

暴力dfs30

 

<span style="font-size:14px;">var
    n,l,a,b,ans         :longint;
    i                   :longint;
    last                :array[0..100010] of longint;
    t                   :array[0..100010] of longint;
    vis                 :array[0..100010] of boolean;
    pre,other           :array[0..200010] of longint;
procedure connect(x,y:longint);
begin
   inc(l);
   pre[l]:=last[x];
   last[x]:=l;
   other[l]:=y;
end;

procedure dfs(x:longint);
var
    p,q:longint;
begin
   q:=last[x];
   vis[x]:=true;
   while (q<>0) do
   begin
      p:=other[q];
      if not vis[p] then
      begin
      t[p]:=t[x]+1;
      dfs(p);
      end else if t[x]-t[p]+1>ans then ans:=t[x]-t[p]+1;
      q:=pre[q];
   end;
   vis[x]:=false;
end;

begin
   assign(input,'aya.in');reset(input);
   assign(output,'aya.out');rewrite(output);
   read(n);
   connect(1,2);
   connect(2,1);
   connect(1,3);
   connect(3,1);
   connect(2,3);
   connect(3,2);
   for i:=4 to n do
   begin
      read(a,b);
      connect(i,a);
      connect(i,b);
      connect(a,i);
      connect(b,i);
   end;
   t[1]:=1;
   dfs(1);
   writeln(ans);
<strong>   close(input);close(output);
end.
</strong></span>

好,下面我们切入正题——满分是怎么来的 0.0

 

(五体投地的膜拜r神 ,orzorzorz

 

正解给的是树型DP,但这里是贪心做法(其实原理是一样一样的==

咱们用a[i,1] a[i,2] 来表示第i个点连接的两个点,且保证 a[i,1]<a[i,2]

然后咱们要考虑怎样去记数了=w=

bb[1,2] 表示12 两点左右两边满足题目要求的点数和(不包括1 2 两个点本身)

同理,bb[2,3] bb[1,3]  

(数组bb中不包括1 2 3中任意一点)

那么其他点如何表示呢?

b[i,1] 表示第i个点与 a[i,1] 两点左右点数和(不包括i a[i,1]); b[i,2] 同理=w=

(看不懂含义?没关系下面有多种解释方法,选择一个觉得像正常人说得话的就好了orz

(关于它的含义,有一下几种表达方法,选一个能看懂的理解一下,意思都是一样的,请包容我一个作文从来不怎么好的渣渣orz

1、表示两点之间连的这条边满足要求的的左右两边点数和(除去两点本身);

2、表示同时过两点的满足要求的最多景点数(不包括两点本身)

3、表示两点在满足要求前提下所能串起的最多景点数(不包括两点本身)

)

注意,数组bb中不包括123中任意点)

例如下图(不堪入目),bb[2,3]=1;

 

好,数组的含义理解了,这仅仅是预热,接下来我们就该开始思考,

什么样的情况是满足要求的呢?这些数组又该如何更新呢=w=

首先,由于我们的b数组和bb 数组中并没有包括两点本身,所以每形成一个三满足题意的三元环我们的ans更新分为3部分:

 

 

我们以点1 2 3 为例,

对它的更新,需要三条边(红色圈出)的bb数组 以及 三个点本身

所以:

   ans=maxans,bb[1,2]+bb[2,3]+bb[1,3]+3)

如果是点4呢?

i=4

   Ans=max(ans.,bb[a[i,1],a[i,2]]+bb[i,1]+bb[i,2]+3) (原本的a[i,1]a[i,2] 之间的+两条边)

那么,再一般一点的情况,a[i,1] a[i,2] 不是 [1,3]的数呢?

唯二的区别在于bb数组变成了b数组并且并不是b[a[i,1],a[i,2]] 而是不同情况的不同边,

具体见下面的具体分析

 

Ok,开始分类讨论=w=

、a[i,2]<=3

由于我们已经保证了a[i,1]<a[i,2] ,所以当a[i,2]<=3 时,显然点i连接的两个点本来就已经形成三元环的1 2 3 中的两点,

就如上面那幅不堪入目的图一样,4号点的插入就是这种情况,ans的更新如上:

 Ans=max(ans.,bb[a[i,1],a[i,2]]+bb[i,1]+bb[i,2]+3)

同时,我们会发现bb[a[i,1],a[i,2] 的数值也发生了相应变化(对应区域范围内多了两条边和一个点,同时那两条边的b也满足了此时的bb[a[i,1],a[i,2]):

bb[a[i,1],a[i,2]=maxbb[a[i,1],a[i,2]b[i,1]+b[i,2]+1)

 

此时,1/3已经完成了=w=

 

二、a[i,2]>4

此时稍微复杂了一点,正如上面所提:另一边不再是 b[a[i,1],a[i,2] 而是不同情况的不同边

(1)a[a[i,2],1]=a[i,1]

好吧,翻译成一般语言就是 i所连的大的那个点所连的小节点  与 i所连的小节点 是同一个点,此时会出现下图(保护好眼睛)的情况(用1表示a[i,1],2表示a[i,2] ,空白点为a[a[i,2],2]

 

 

此时,我们发现,形成三元环的点是 i a[i,1]  a[i,2]

边是 b[i,1] b[i,2] b[a[i,2],1]

所以

  Ans=max(ans,b[a[i,2],1]+b[i,1]+b[i,2]+3)

同时 b[a[i,2],1]=maxb[a[i,2],1]b[i,1]+b[i,2]+1)

 

 

好,2/3的工作完成了,胜利就在前方=w=

 

(2)a[a[i,2],1]<>a[i,1](不等于)

那么此时我们还剩下两种小情况:

a[a[i,2],2]=a[i,1]

于是还是上面那个图,空白点含义编程 a[a[i,2],1]

此时,我们发现,形成三元环的点是 i a[i,1]  a[i,2]

边是 b[i,1] b[i,2] b[a[i,2],2]

所以

 Ans=max(ans,b[a[i,2],2]+b[i,1]+b[i,2]+3)

同时 b[a[i,2],2]=maxb[a[i,2],2]b[i,1]+b[i,2]+1)

 

‚完全不同

于是就会形成一种尴尬的局面:

 

 

但是,我们根据连接的先后顺序可知,a[a[i,2],2]到最后一定会与a[i,1]相连,

 

 

即等效成

 

 

于是形成了上面a[a[i,2],2]=a[i,1]  的情况,于是我们便 合二为一 即可

 

OK,恭喜你99%都已经大功告成了,得意的敲上代码0.0

记住,这时的得意便是日后的后悔,你会发现有wa,还不止一个==

 

为什么?

这时你就要考虑一下你最终输出的结果是什么,我们的ans存的是4~n的最优解,我们还有点 1 2 3 ==

但是,有的同学就会说,没错,我输出的就是bb[1,2]+bb[1,3]+bb[2,3]+3 ,依旧没有AC

那必是啊=。=

当你只输出ans的时候,没有考虑1 23,

当你只输出bb[1,2]+bb[1,3]+bb[2,3]+3 你又没有考虑到其他点的最优解(局部最优解)

怪我喽==

 

所以输出 maxans,bb[1,2]+bb[1,3]+bb[2,3]+3

 

var
    n,ans,l,r           :longint;
    i                   :longint;
    a                   :array[0..100010,0..3] of longint;
    b                   :array[0..100010,0..3] of longint;
    bb                  :array[0..3,0..3] of longint;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;

procedure swap(var a,b:longint);
var
    c:longint;
begin
   c:=a;a:=b;b:=c;
end;

begin
   assign(input,'aya.in');reset(input);
   assign(output,'aya.out');rewrite(output); 
   read(n);
   for i:=4 to n do
   begin
      read(a[i,1],a[i,2]);
      if (a[i,1]>a[i,2]) then swap(a[i,1],a[i,2]);
   end;
   //
   for i:=n downto 4 do
   begin
      l:=a[i,1];
      r:=a[i,2];
      if (r<=3) then
      begin
         ans:=max(ans,bb[l,r]+b[i,1]+b[i,2]+3);
         bb[l,r]:=max(bb[l,r],b[i,1]+b[i,2]+1);
      end else
      begin
         if (l=a[r,1]) then
         begin
            ans:=max(ans,b[r,1]+b[i,1]+b[i,2]+3);
            b[r,1]:=max(b[r,1],b[i,1]+b[i,2]+1);
         end else
         begin
            ans:=max(ans,b[r,2]+b[i,1]+b[i,2]+3);
            b[r,2]:=max(b[r,2],b[i,1]+b[i,2]+1);
         end;
      end;
   end;
   //
   writeln(max(ans,bb[1,2]+bb[2,3]+bb[1,3]+3));
   close(input);close(output);
end.

AC=w=


数据请见   https://www.jianguoyun.com/p/DTuwgroQsq2OBhiakR4        里的aya即为本题

                                                                     ——by Eirlys


转载请注明出处=w=


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值