[USACO 2010 OPEN]SLIED

时间:2022-12-14 14:27:01

传送门

这道题的题意描述简直有毒。题没看完一眼分层图,然后火速敲了个堆优化的dijkstra,然后就被样例教做人了QAQ

这里说的最坏的情况让我很迷茫?感觉很难判定到底什么是最坏的情况以及确定了最坏的情况应该怎么办....然后我就去扒了扒别人好几年前的代码,耐着性子把pascal的代码看完..恍然大悟..

题目那样描述确实有点不妥当,但是如果说清楚了,那这就成一个完全的裸题了。

要求在最坏的情况下收益最大,假设你现在在一个点上,你已经失误了$i$次,那么还允许你失误$K-i$次,要求最大收益。这里之所以不能采取分层图也是这个原因,到了不同的状态,图的构建方案是不同的。

所以在具体实现时,对于每个状态,需要得到

1.如果不失误,那么到目标状态的最大收益。

2.如果失误,到目标状态的最小收益。

然后对这两个值取$min$,因为题目要求的状况是worst。

//oj 1601
//by Cydiater
//2016.10.6
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
using namespace std;
#define ll long long
#define up(i,j,n)        for(int i=j;i<=n;i++)
#define down(i,j,n)        for(int i=j;i>=n;i--)
const ll MAXN=2e5+5;
const ll oo=1000000000000LL;
inline ll read(){
    char ch=getchar();ll x=0,f=1;
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll N,M,K,LINK[MAXN],len=0,f[MAXN][15];
struct edge{
    ll y,next,v;
}e[MAXN];
bool vis[MAXN];
namespace solution{
    inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
    void init(){
        N=read();M=read();K=read();
        up(i,1,M){
            ll x=read(),y=read(),v=read();
            insert(x,y,v);
        }
    }
    void dfs(int node,int fa){
        if(vis[node])return;
        for(int i=LINK[node];i;i=e[i].next)if(e[i].y!=fa)dfs(e[i].y,node);
        up(j,0,K){
            for(int i=LINK[node];i;i=e[i].next)if(e[i].y!=fa)
                f[node][j]=max(f[node][j],f[e[i].y][j]+e[i].v);
            if(j<K)for(int i=LINK[node];i;i=e[i].next)if(e[i].y!=fa)
                f[node][j]=min(f[node][j],f[e[i].y][j+1]+e[i].v);
            f[node][j]=max(f[node][j],0LL);
        }
        vis[node]=1;
    }
    void slove(){
        up(i,1,N)up(j,0,K)f[i][j]=-oo;
        memset(vis,0,sizeof(vis));
        dfs(1,0);
    }
    void output(){
        cout<<f[1][0]<<endl;
    }
}
int main(){
    //freopen("input.in","r",stdin);
    using namespace solution;
    init();
    slove();
    output();
    return 0;
}