題面
牛牛所在的W市是一個不太大的城市,城市有n個路口以及m條公路,這些雙向連通的公路長度均爲1。牛牛在玩寶可夢Go,衆所周知呢,這個遊戲需要到城市的各個地方去抓寶可夢,假設現在牛牛知道了接下來將會刷出k只寶可夢,他還知道每隻寶可夢的刷新時刻、地點以及該寶可夢的戰鬥力,如果在寶可夢刷新時,牛牛恰好在那個路口,他就一定能夠抓住那隻寶可夢。
由於遊戲公司不想讓有選擇恐懼症的玩家爲難,所以他們設計不存在任何一個時刻同時刷出兩隻及以上的寶可夢。
假設不存在任何一個時刻會同時刷出兩隻寶可夢,牛牛一開始在城市的1號路口,最開始的時刻爲0時刻,牛牛可以在每個時刻之前移動到相鄰他所在位置的路口,當然他也可以保持原地不動,他現在想知道他能夠捕獲的寶可夢戰鬥力之和最大爲多少?
樣例一
3 2
1 2
2 3
3
1 1 5
2 3 10
3 2 1
11
樣例二
1 0
3
1 1 100
100 1 10000
10000 1 1
10101
樣例三
3 2
1 2
2 3
1
1 3 1000000000
0
樣例四
3 2
1 2
2 3
1
1 2 1000000000
1000000000
首先,關於求解任意兩點之間的最短路,是爲了求解出任意兩點之間相互達到所需要的最小花費時間。
然後的話,這裏有個剪枝,除去剪枝的話,複雜度優化一點可以達到的是,這個複雜度是怎樣來的呢?就是我們去求維護一個dp[點][時刻],然後我們每次因爲只會更新一個點,所以我們可以去枚舉N個點,包括自己,因爲可以待着不動,我們用log的方法(二分查詢)查詢前面哪一個時刻可以轉移到目前時刻,這是複雜度爲的寫法了。
其實會發現,這裏有可以剪枝的部分,剪枝之後的複雜度會變成,或者說是,因爲圖的最大的大小就是200,所以圖的直徑最長也不過是199,方便寫,我們寫到200,於是乎,200以上的距離我們可以任意到達,那麼同樣的,距當前詢問有200次詢問之前的詢問,我們可以直接繼承,所以這裏可以維護一個前綴最大值。然後,我們每次只需要去看前1~200次中的詢問,是否可以得到,以及跟最大值的比較,然後是更新答案。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define IINF 0x3f3f3f3f3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e2 + 7;
int N, M, K, head[maxN], cnt, mp[maxN][maxN], t[maxN];
ll dp[100005] = {0}, ans = 0;
inline void floyd()
{
for(int k=1; k<=N; k++)
{
for(int j=1; j<=N; j++)
{
for(int i=1; i<=N; i++)
{
if(i == j) continue;
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
}
}
}
}
struct node
{
int t, p; ll val;
node(int a=0, int b=0, ll c=0):t(a), p(b), val(c) {}
inline void In_Put() { scanf("%d%d%lld", &t, &p, &val); }
friend bool operator < (node e1, node e2) { return e1.t < e2.t; }
}op[100005];
int Lsan[100005];
int main()
{
scanf("%d%d", &N, &M);
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++) mp[i][j] = INF;
mp[i][i] = 0;
}
for(int i=1, u, v; i<=M; i++)
{
scanf("%d%d", &u, &v);
mp[u][v] = mp[v][u] = 1;
}
floyd();
scanf("%d", &K);
for(int i=1; i<=K; i++)
{
op[i].In_Put();
Lsan[i] = op[i].t;
}
sort(Lsan + 1, Lsan + K + 1);
sort(op + 1, op + K + 1);
op[0] = node(0, 1, 0);
ll pre_max = 0;
for(int i=1; i<=K; i++)
{
if(i > 200)
{
pre_max = max(pre_max, dp[i - 200]);
dp[i] = op[i].val + pre_max;
}
else
{
dp[i] = -IINF;
}
for(int j=1; j<=200 && i - j >= 0; j++)
{
if(op[i].t - op[i - j].t >= mp[op[i].p][op[i - j].p])
{
dp[i] = max(dp[i], dp[i - j] + op[i].val);
}
}
ans = max(ans, dp[i]);
}
printf("%lld\n", ans);
return 0;
}