BZOJ3875 AHOI2014/JSOI2014騎士遊戲(動態規劃)
阿新 • • 發佈:2018-10-07
老師 con ack 有意思 mes cstring cto -s bzoj3875
容易想到設f[i]為殺死i號怪物所消耗的最小體力值,由後繼節點更新。然而這顯然是有後效性的,正常的dp沒法做。
雖然spfa已經死了,但確實還是挺有意思的。只需要用spfa來更新dp值就可以了。
記得我們老師說過某位學長省選前幾乎什麽省選算法都不會,然後當場切掉了這題,然後進了省隊,然後拿了cu,最後進了pku。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define N 200010 #define ll long long #define inf 100000000000000000 ll read() { ll x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,q[N]; ll f[N];bool flag[N]; struct data { ll x,y; vector<int> from,to; }a[N]; int inc(int &x){x++;if (x>n+1) x-=n+1;return x;} bool cmp(const int &a,const int&b) { return f[a]<f[b]; } void spfa() { int head=0,tail=n;for (int i=1;i<=n;i++) q[i]=i,flag[i]=1,f[i]=a[i].y; sort(q+1,q+n+1,cmp); do { int x=q[inc(head)],s=a[x].from.size();flag[x]=0; for (int i=0;i<s;i++) { int y=a[x].from[i]; int t=a[y].to.size();ll sum=a[y].x; for (int j=0;j<t;j++) { sum+=f[a[y].to[j]]; if (sum>f[y]) break; } if (sum<f[y]) { f[y]=sum; if (!flag[y]) q[inc(tail)]=y,flag[y]=1; } } }while (head!=tail); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3875.in","r",stdin); freopen("bzoj3875.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<=n;i++) { a[i].x=read(),a[i].y=read(); int t=read(); while (t--) { int x=read(); a[x].from.push_back(i), a[i].to.push_back(x); } } spfa(); cout<<f[1]; return 0; }
BZOJ3875 AHOI2014/JSOI2014騎士遊戲(動態規劃)