链接:https://ac.nowcoder.com/acm/contest/3004/J
来源:牛客网

牛牛所在的W市是一个不太大的城市,城市有n个路口以及m条公路,这些双向连通的公路长度均为1,保证你可以从一个城市直接或者间接移动到所有的城市。牛牛在玩宝可梦Go,众所周知呢,这个游戏需要到城市的各个地方去抓宝可梦,假设现在牛牛知道了接下来将会刷出k只宝可梦,他还知道每只宝可梦的刷新时刻、地点以及该宝可梦的战斗力,如果在宝可梦刷新时,牛牛恰好在那个路口,他就一定能够抓住那只宝可梦。 
 

 

 

 

 

 

 

 

看题解前:不会,溜了

看题解后:floyd,排序,01背包......................

 

 

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100005;
const int MAXP=505;
const long long INF=1LL<<60;
long long premax,dp[MAXN],ans,dis[MAXP][MAXP];
int n,m,N,u,v;
struct node
{
    int p,t;
    long long val;
}a[MAXN];
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=n;++j)
        {
            dis[i][j]=i==j?0:INF;
        }
    }
    for(int i=1;i<=m;++i)
    {
        scanf("%d %d",&u,&v);
        dis[u][v]=dis[v][u]=1;
    }
    for(int k=1;k<=n;++k)
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)
            {
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    scanf("%d",&N);
    for(int i=1;i<=N;++i)
    {
        scanf("%d %d %lld",&a[i].t,&a[i].p,&a[i].val);
    }
    sort(a+1,a+1+N,[](const node &A,const node &B){return A.t<B.t;});
    a[0].p=1;
    for(int i=1;i<=N;++i)
    {
        if(i>200)
        {
            premax=max(premax,dp[i-200]);
            dp[i]=a[i].val+premax;
        }
        else
        {
            dp[i]=-INF;
        }
        for(int j=1;j<=200&&i-j>=0;++j)
        {
            if(a[i].t-a[i-j].t>=dis[a[i].p][a[i-j].p])
            {
                dp[i]=max(dp[i],dp[i-j]+a[i].val);
            }
        }
        ans=max(ans,dp[i]);
    }
    printf("%lld\n",ans);
    return 0;
}