1 条题解

  • 0
    @ 2025-8-24 21:36:08

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar BFSBFSBFSBFS
    **

    搬运于2025-08-24 21:36:08,当前版本为作者最后更新于2018-01-20 14:58:20,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    迷宫入口去哪了..

    题意.给出1个图.图上有2人.每个人每个回合.可以选择移动到相邻点.或者原地不动.

    当2个人相遇就会被....

    其中loidc会尽可能延长回合数(就是尽量不相遇.).或者干脆让cony追不上..

    而cony会尽力追赶loidc.

    由loidc先手.2人均使用最佳策略..求cony能否追上.以及能追上时.至少的回合数.

    由于loidc用的最佳策略.显然不会去送..那么对于loidc来讲.就是要求最多的回合数.


    明确题意后.来看看双方的行动策略.

    cony是要追赶loidc的.仔细想想就能明白.cony不会停留在1个点上.

    为什么.?

    若cony选择在1个点停留.接下来loidc可以继续逃跑.给予了跑掉的可能性.

    如果loidc发现逃跑是不行的.Ta依然可以选择停留在原来的点上.相当于先手权仍然在cony这里.但白白浪费了1回合.

    不管怎样.停留在1处都不是好方法.所以每回合cony必定移动.


    这个结论先放在1边.再看看loidc的策略.

    如果说要cony追不上的话.loidc唯1的办法是.在被cony抓到之前跑进环.

    环至少是3个点吧..2个点的明显是送....

    这个好理解吧..在环上1跑1追.速度相同.是追不上的...?

    这里有反例了.3角形.

    (黑色的是点..红色的是边..丑..).

    可以看到,如果loidc在1号点.cony在3号点.即使跑进2号点也无济于事.cony可以马上到达2号点.loidc只能被迫退出3元环..

    可是.题目告诉你了没有3角形...那这条就不用管了..

    也就是.只要loidc跑进至少4个点组成的环.loidc就不会被抓到.


    好了.策略分析完毕.那么loidc要怎样跑呢.?

    显然.我们要尽快到达环.当然是走最短路了..

    但是还有cony啊.不能被捉到.

    我们已经知道,cony不会不动.那么让cony也跑最短路.比较1下就行了..

    cony难道不能放弃最短路.去拦截在半路loidc.?

    既然都能拦截了.那去拦截的这条路+lodic剩下的最短路.又可以组成新的最短路..

    也就是不管怎样.cony1定跑在最短路上.

    问题就变成了求2点的单元最短路.

    设loidc到第i个点的最短路为d[i]d[i].cony到第i个点的最短路为e[i]e[i].

    如果有d[i]<e[i]d[i] < e[i],并且ii点在有4个点以上组成的环上面.的话.输出NO.

    那么跑不进环怎么办.?

    只能找个地方躲起来等....

    就是说.对于每个d[i]<e[i]d[i] < e[i].输出max(e[i])max(e[i]).

    就是cony最慢要跑的时间了..

    Diu代码..

    program P2302;
     uses math;
     type
      wb=array[0..3001] of longint;
      wa=record
       n,t:longint;
      end;
     var
      a:array[0..30001] of wa;
      b,c,h,f,stl,instl,DFS,DFN,t:wb;
      i,m,n,p,dsum,sumstl,ac,bc,upass,smax,x,y:longint;
     procedure hahainc(x,y:longint);    //前向星遍历边..
      begin
       inc(p);
       a[p].n:=h[x];
       a[p].t:=y;
       h[x]:=p;
      end;
     procedure hahaDFS(k,lp:longint);  //用tarjan求环..
      var
       j,p,upass:longint;
      procedure hahaapps;        //初始化工作..
       begin
        inc(dsum);
        DFS[k]:=dsum;           //DFS序.
        DFN[k]:=dsum;           //最靠前访问过的点的DFS序.
        inc(sumstl);            //进栈.
        stl[sumstl]:=k;           //.
        instl[k]:=1;            //是否在栈内的判断..
        f[k]:=1;                //是否访问过的判断..
       end;
      begin
       hahaapps;
       j:=h[k];
       while a[j].n<>-1 do      //遍历边.
        begin
         p:=a[j].t;
         j:=a[j].n;
         if p=lp then continue; //这个是过滤2点环.因为这是无向边..
         if f[p]=0 then
          begin
           hahaDFS(p,k);
           DFN[k]:=min(DFN[k],DFN[p]); //环标记传递.
          end
                   else if instl[p]=1 then DFN[k]:=min(DFN[k],DFS[p]); //栈内形成环.
        end;
       if stl[sumstl]=k then upass:=1 //这个是过滤单点环(..)..
                        else upass:=0;
       if DFN[k]=DFS[k] then
        repeat
         p:=stl[sumstl];
         if upass=0 then t[p]:=1;     //t是环标记.
         instl[p]:=0;
         dec(sumstl);
        until p=k;
      end;
     procedure hahadij(var b:wb;k:longint); //做2遍dij..
      var
       i,j,p:longint;
      begin
       filldword(b,length(b),1008208820);
       filldword(f,length(f),0);
       b[k]:=0;
       for i:=1 to n do
        begin
         p:=0;
         for j:=1 to n do
          if (f[j]=0) and (b[j]<b[p]) then p:=j;
         f[p]:=1;
         j:=h[p];
         while a[j].n<>-1 do
          begin
           if b[p]+1<b[a[j].t] then b[a[j].t]:=b[p]+1; //权值是1了..
           j:=a[j].n;
          end;
        end;
      end;
     begin
      readln(n,m,ac,bc);
      filldword(h,length(h),0);
      p:=0;
      for i:=1 to m do
       begin
        readln(x,y);
        hahainc(x,y);
        hahainc(y,x);
       end;
      a[0].n:=-1;
      filldword(f,length(f),0);
      filldword(t,length(t),0);
      filldword(instl,length(instl),0);
      sumstl:=0;
      dsum:=0;
      for i:=1 to n do
       if f[i]=0 then hahaDFS(i,0);
      {for i:=1 to n do
       writeln(DFS[i],' ',DFN[i],' ',t[i]);}
      hahadij(b,ac);
      hahadij(c,bc);
      upass:=0;
      smax:=0;
      for i:=1 to n do
       begin
        if (c[i]>b[i]) and (t[i]=1) then upass:=1;    //能否跑进环的标记.
        if (c[i]>b[i]) then smax:=max(smax,c[i]);     //最长的回合数..
       end;
      if upass=0 then writeln(smax)
                 else writeln('NO');
     end.
    

    欢迎Hack.

    (ಡωಡ).

    • 1

    信息

    ID
    1254
    时间
    1000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者