[AHOI2014]骑士游戏

【故事背景】
长期的宅男生活中,JYY又挖掘出了一款RPG游戏。在这个游戏中JYY会
扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽。
【问题描述】
在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻
击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。当然了,一般来说,相比普通攻击,法术攻击会消耗更多的体力值(但由于游戏系统bug,并不保证这一点)。
游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入
侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?
Input

第一行包含一个整数N。
接下来N行,每行描述一个怪兽的信息;
其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,
普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力,同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。
Output

输出一行一个整数,表示最少需要的体力值。

Sample Input

4

4 27 3 2 3 2

3 5 1 2

1 13 2 4 2

5 6 1 2
Sample Output

26
HINT

【样例说明】

首先用消耗4点体力用普通攻击,然后出现的怪兽编号是2,2和3。花费

10点体力用法术攻击杀死两个编号为2的怪兽。剩下3号怪兽花费1点体力进

行普通攻击。此时村庄里的怪兽编号是2和4。最后花费11点体力用法术攻击

将这两只怪兽彻底杀死。一共花费的体力是4+5+5+1+5+6=26。

【数据范围】

2<=N<=2*10^5,1<=Ri,Sigma(Ri)<=10^6,1<=Ki,Si<=5*10^14

分析:要杀死一个怪物,要么直接法术攻击,要么普通攻击到某一位置在用法术攻击杀死新产生的怪兽。
cost[i]=min(k[i],s[i]+∑cost[son[i]])
这是一个环,但这个环到某一个地方必定会断掉(选择k[i])
类似spfa,但队列中存的是待更新的点,一开始dis[i]都赋值为k[i],所以计算一个点,如果它更新了就可能更新它的“父亲”,把它的父亲入队。

program bzoj3875;
var t,l,i,n,p,top,tail,u,ss1,j,l1:longint;
    head1,r,head:array[1..200010]of longint;
    b:array[1..3000010]of longint;
    flag:array[1..200010]of boolean;
    edge,edge1:array[1..2000010,1..2]of longint;
    cost,s,k,ss:array[1..200010]of int64;
procedure add(x,y:longint);
begin
 l:=l+1;
 edge[l,1]:=x;
 edge[l,2]:=head[y];
 head[y]:=l;
end;
procedure add1(x,y:longint);
begin
 l1:=l1+1;
 edge1[l1,1]:=y;
 edge1[l1,2]:=head1[x];
 head1[x]:=l1;
end;
begin
 read(n);
 for i:=1 to n do
  begin
  head[i]:=-1;
  head1[i]:=-1;
  end;
 for i:=1 to n do
  begin
   read(s[i],k[i],r[i]);
   ss[i]:=s[i];
   for j:=1 to r[i] do
    begin
     read(t);
     add(i,t);
     add1(i,t);
    end;
  end;
 for i:=1 to n do
  begin
   p:=head1[i];
   while p<>-1 do
    begin
     ss[i]:=ss[i]+k[edge1[p,1]];
     p:=edge1[p,2];
    end;
  end;
 for i:=1 to n do cost[i]:=k[i];
 fillchar(flag,sizeof(flag),false);
 top:=1;tail:=n;
 for i:=1 to n do b[i]:=i;
 repeat
  if ss[b[top]]<cost[b[top]] then
   begin
    p:=head[b[top]];
    while p<>-1 do
     begin
      u:=edge[p,1];
      ss[u]:=ss[u]-cost[b[top]]+ss[b[top]];
      if flag[u] then
       begin
        tail:=tail+1;
        b[tail]:=u;
        flag[u]:=false;
       end;
      p:=edge[p,2];
     end;
    cost[b[top]]:=ss[b[top]];
   end;
  flag[b[top]]:=true;
  top:=top+1;
 until top>tail;
 writeln(cost[1]);
end.

你可能感兴趣的:([AHOI2014]骑士游戏)