1. 程式人生 > >P4042 [AHOI2014/JSOI2014]騎士遊戲

P4042 [AHOI2014/JSOI2014]騎士遊戲

none lse head printf 初始 src pro 檢查 style

前往>>暴風城

第一次寫SPFA!(慚愧

對於某個怪獸,殺死它的最小消耗 = min(它的魔法消耗,它的物理消耗 + 殺死它所有兒子的消耗)

可以看出,一個點可能被它的兒子更新,並且可能去更新它的父親。

考慮用最短路解決這道題,從一個假設的起點0出發,要求它到1的最短距離。1~n每個點的距離初始應為INF。

將每個怪物的消耗更新為它的魔法消耗,並加入隊列;

彈出隊首,檢查它能不能被更新。如果可以,則說明它有可能更新它的父親,將它的所有父親加入隊列;

直到隊列為空為止。

代碼如下

技術分享圖片
#include<cstdio>
#include<iostream>
#include
<cstring> #include<cmath> #define MogeKo qwq #include<queue> using namespace std; const int maxn = 2e6; int n,r,x; long long ad[maxn],ap[maxn],dis[maxn]; int head[maxn][2],to[maxn][2],nxt[maxn][2],cnt[2]; bool vis[maxn]; queue <int> q; void add(int x,int y,int op) { to[
++cnt[op]][op] = y; nxt[cnt[op]][op] = head[x][op]; head[x][op] = cnt[op]; } void SPFA() { for(int i = 1; i <= n; i++) { q.push(i); vis[i] = true; } while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; long
long tem = ad[u]; for(int i = head[u][1]; i; i = nxt[i][1]) tem += dis[to[i][1]]; if(tem >= dis[u])continue; dis[u] = tem; for(int i = head[u][0]; i; i = nxt[i][0]) { int v = to[i][0]; if(vis[v])continue; q.push(v); vis[v] = true; } } } int main() { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%lld%lld%d",&ad[i],&ap[i],&r); dis[i] = ap[i]; for(int j = 1; j <= r; j++) { scanf("%d",&x); add(x,i,0); add(i,x,1); } } SPFA(); printf("%lld",dis[1]); return 0; }
View Code

P4042 [AHOI2014/JSOI2014]騎士遊戲