解题报告 Trick

Trick

【题目描述】

暴躁的稻草人,最终以自爆来给我们的队伍致命一击,全队血量见底,稻草人也一分为二。还好我们有雨柔妹子,瞬间精力回满。不过事后姜小弟和龙腹黑就开始了报复。

他们读取存档,将若干暴躁的稻草人活捉。然后将它们放到一个迷宫的入口。迷宫是有向图。此刻暴躁的稻草人们在1号位置,而迷宫出口在n号位置。因为稻草人会自爆,所以他每经过一条路数量就会加倍。每条路上敌人,会消耗稻草人c[i](c[i]为负值);当然有些时候路上也会遇到止血草之类的东西,这时候就可以补充一些稻草人(c[i]为正值)。如果小稻草人死光了,那么稻草人也就可以看做是挂了。希望你帮助稻姜龙二人算出用最少的初始稻草人使其能够走出迷宫

【输入格式】

第一行两个数N<=50000),M<=100000)表示点位数与边数。

以下M行,每行三个数abc表示ab两点间的边权是c|c|<=10000

【输出格式】

输出仅一个整数,表示最小初始稻草人数(在 [1,10000] 之间

【输入样例】

  5 4
  1 2 -3
  1 3 -6
  3 4 1
  4 5 -9

【输出样例】

  4

 

首先,他给出答案的范围了,所以可以二分答案。

二分一开始有几个,然后跑最长路,看看能不能到头。

并且,如果遇到了环,则稻草人可以无限增加,所以可以直接得到答案,但还要继续二分,因为他让求最小的。

 

不过,还有第二种思路:可以发现,当用最少的稻草人开始走的时候,到达终点,一定只剩一个。

所以,倒着搜,就可以了。

 

 

 

二分答案(魂之挽歌)

program test2;

const dd=100000;

type bian=record

      y,l,next:longint;

     end;

var a:array[0..100010]of bian;

    dist:array[0..50010]of int64;

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

    d:array[0..100000]of longint;

    g:array[0..50000]of longint;

    s:array[0..50001]of longint;

    i,j,m,n,x,y,l,ans:longint;

function spfa(k:longint):boolean;

var t,w,i,x:longint;

begin

    fillchar(dist,sizeof(dist),0);

    fillchar(v,sizeof(v),0);

    fillchar(s,sizeof(s),0);

    t:=0;w:=1;d[w]:=1;v[1]:=true;dist[1]:=k;

    s[1]:=1;

    while t<>w do

    begin

        t:=(t+1)mod dd;x:=d[t];i:=g[x];

        while i<>0 do

        begin

            if dist[a[i].y]<dist[x]*2+a[i].l then

            begin

                dist[a[i].y]:=dist[x]*2+a[i].l;

                inc(s[a[i].y]);

                if s[a[i].y]>n then exit(true);

                if not v[a[i].y] then

                begin

                    v[a[i].y]:=true;

                    w:=(w+1)mod dd;

                    d[w]:=a[i].y;

                end;

            end;

            i:=a[i].next;

        end;

    end;

    if dist[n]>0 then exit(true);

    exit(false);

end;

procedure find(l,r:longint);

var mid:longint;

begin

    if l>r then exit;

    mid:=(l+r)shr 1;

    if spfa(mid) then

    begin

        ans:=mid;

        find(l,mid-1);

    end

    else find(mid+1,r);

end;

begin

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

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

    readln(n,m);

    for i:=1 to m do

    begin

        readln(x,y,l);

        a[i].y:=y;

        a[i].l:=l;

        a[i].next:=g[x];

        g[x]:=i;

    end;

    find(1,10000);

    writeln(ans);

close(input);close(output);

end.

 

 

 

倒着推(Ray

program lonely;

  const

    maxn=100010;

  type

    nod=record

      x,y,len,next:longint;

    end;

  var

    map:array[0..100010] of nod;

    first:array[0..50000] of longint;

    que:array[0..100010] of longint;

    dist:array[0..50010] of int64;

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

 

    temp,head,tail,tot,x,y,len,t,i,n,m:longint;

 

  begin

    assign(input,'trick.in');

    reset(input);

    assign(output,'trick.out');

    rewrite(output);

    readln(n,m);

    for i:=1 to m do

      begin

        readln(y,x,len);

        len:=-len;

        map[i].x:=x;map[i].y:=y;map[i].len:=len;

        map[i].next:=first[x];first[x]:=i;

      end;

    fillchar(que,sizeof(que),0);

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

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

    head:=0;tail:=1;

    que[tail]:=n;

    dist[n]:=1;

    v[n]:=true;

    while head<>tail do

      begin

        inc(head);

        if head>maxn then head:=1;

        x:=que[head];

        t:=first[x];

        while t<>0 do

          begin

            y:=map[t].y;

            temp:=dist[x]+map[t].len;

            if ((temp-1) div 2+1<dist[y])and(dist[x]>0)and(dist[y]>1) then

              begin

                dist[y]:=(temp-1) div 2+1;

                if dist[y]<0 then dist[y]:=1;

                if not v[y] then

                  begin

                    v[y]:=true;

                    inc(tail);

                    if tail>maxn then tail:=1;

                    que[tail]:=y;

                  end;

              end;

            t:=map[t].next;

          end;

        v[x]:=false;

      end;

    writeln(dist[1]);

    close(input);

    close(output);

  end.

 

 

 

 

 

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/SueMiller/p/2216482.html