【故事背景】
长期的宅男生活中,JYY又挖掘出了一款RPG游戏。在这个游戏中JYY会
扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽。
【问题描述】
在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻
击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能 经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。当然了,一般来说,相比普通攻击,法术攻击会消耗更多的体力值 (但由于游戏系统bug,并不保证这一点)。
游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入
侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?
第一行包含一个整数N。
接下来N行,每行描述一个怪兽的信息;
其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,
普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力,同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。
【样例说明】
首先用消耗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
1 //It is made by jump~
2 #include <iostream>
3 #include <cstdlib>
4 #include <cstring>
5 #include <cstdio>
6 #include <cmath>
7 #include <algorithm>
8 #include <ctime>
9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 200011;
21 const int MAXM = 4000011;
22 int n,m;
23 LL f[MAXN],g[MAXN];//f[i]表示消灭掉i的最小花费,g[i]表示物理攻击i后并消灭产生新怪物后的开销
24 int first[MAXN],next[MAXM],to[MAXM];
25 int head[MAXN],ecnt,ccnt;
26 bool vis[MAXN];
27 queue<int>Q;
28 struct edge{
29 int next,to;
30 }e[MAXM];
31
32 inline int getint()
33 {
34 int w=0,q=0;
35 char c=getchar();
36 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar();
37 if (c==‘-‘) q=1, c=getchar();
38 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar();
39 return q ? -w : w;
40 }
41
42 inline LL getlong()
43 {
44 LL w=0,q=0;
45 char c=getchar();
46 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar();
47 if (c==‘-‘) q=1, c=getchar();
48 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar();
49 return q ? -w : w;
50 }
51
52 inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
53
54 inline void link2(int x,int y){ e[++ccnt].next=head[x]; head[x]=ccnt; e[ccnt].to=y; }
55
56 inline void SPFA(){
57 while(!Q.empty()) {
58 int u=Q.front(); Q.pop(); vis[u]=0;
59 if(f[u]<=g[u]) continue;//已经更优
60 for(int i=head[u];i;i=e[i].next) {
61 if(!vis[e[i].to]) vis[e[i].to]=1,Q.push(e[i].to);
62 g[e[i].to]-=f[u];
63 g[e[i].to]+=g[u];
64 }
65 f[u]=g[u];//存在更优的策略
66 }
67 }
68
69 inline void work(){
70 n=getint(); int x;
71 for(int i=1;i<=n;i++) {
72 g[i]=getlong(); f[i]=getlong();//初值定为物理攻击和法力攻击
73 m=getint(); Q.push(i); vis[i]=1;
74 for(int j=1;j<=m;j++) x=getint(),link(i,x),link2(x,i);
75 }
76 for(int i=1;i<=n;i++) for(int j=first[i];j;j=next[j]) g[i]+=f[to[j]];
77 SPFA();
78 printf("%lld",f[1]);
79 }
80
81 int main()
82 {
83 work();
84 return 0;
85 }