给你一个有向图,边权为经过所需时间
每个点有一个点权,有些点还有有特殊的点权
当你到达一个点后,可以获得该点的点权(重复经过可以重复获得,但不能停留),若在某个时间到某个点,则可获得该特殊点权
现在问你从点1出发走,在时间T回到1得到的最大点权和是多少
3 4 11 0
1 3 4
1 2 1
2 1 3
2 3 2
3 1 4
13
4 8 16 3
3 1 2 4
1 2 1
1 3 1
1 3 2
3 4 3
2 3 2
3 2 1
4 2 1
4 1 5
3 3 5
1 2 5
5 4 20
39
对于上图,小 W 一种为期 11 天的可行旅游方案为 1 → 2 → 1 → 2 → 3 → 1 1 \to 2 \to 1 \to 2 \to 3 \to 1 1→2→1→2→3→1
第 0 天,小 W W W 从城市 1 开始旅行,获得愉悦值 1 并向城市 2 出发。
第 1 天,小 W W W 到达城市 2,获得愉悦值 3 并向城市 1 出发。
第 4 天,小 W W W 到达城市 1,获得愉悦值 1 并向城市 2 出发。
第 5 天,小 W W W 到达城市 2,获得愉悦值 3 并向城市 3 出发。
第 7 天,小 W W W 到达城市 3,获得愉悦值 4 并向城市 1 出发。
第 11 天,小 W W W 到达城市 1,获得愉悦值 1 并结束旅行。
小 W 在该旅行中获得的愉悦值之和为 13。
最优方案为 1 → 3 → 4 → 2 → 3 → 4 → 1 1 \to 3 \to 4 \to 2 \to 3 \to 4 \to 1 1→3→4→2→3→4→1
第 0 天,小 W W W 从城市 1 开始旅行,获得愉悦值 3 并沿道路 3 通行。
第 2 天,小 W W W 到达城市 3,获得愉悦值 2 并沿道路 4 通行。
第 5 天,小 W W W 到达城市 4,由于美食节获得愉悦值 20+4 并沿道路 7 通行。
第 6 天,小 W W W 到达城市 2,获得愉悦值 1 并沿道路 5 通行。
第 8 天,小 W W W 到达城市 3,获得愉悦值 2 并沿道路 4 通行。
第 11 天,小 W W W 到达城市 4,获得愉悦值 4 并沿道路 8 通行。
第 16 天,小 W W W 到达城市 1,获得愉悦值 3 并结束旅行。
小 W 获得的愉悦值之和为 39。
1 ≤ n ≤ 50 , n ≤ m ≤ 501 , 0 ≤ k ≤ 200 , 1 ≤ t i ≤ T ≤ 1 0 9 。 1 \leq n \leq 50,n \leq m \leq 501,0 \leq k \leq 200,1 \leq t_i \leq T \leq 10^9 。 1≤n≤50,n≤m≤501,0≤k≤200,1≤ti≤T≤109。
1 ≤ w i ≤ 5 , 1 ≤ c i ≤ 52501 , 1 ≤ u i , v i , x i ≤ n , 1 ≤ y i ≤ 1 0 9 1 \leq w_i \leq 5,1 \leq c_i \leq 52501,1 \leq u_i, v_i, x_i \leq n,1 \leq y_i \leq 10^9 1≤wi≤5,1≤ci≤52501,1≤ui,vi,xi≤n,1≤yi≤109
我们发现 w w w很小,我们可以把一条边分成若干长度为1的边,这样点最多只有250个
当没有特殊点权时
我们可以用邻接矩阵跑矩阵乘法
时间 O ( ( n w ) 3 l o g T ) O((nw)^3 logT) O((nw)3logT)
如果有特殊点权时直接暴力跑矩阵乘法那时间是 O ( ( n w ) 3 k l o g T ) O((nw)^3 k\ logT) O((nw)3k logT)
会TLE
我们与处理出 f i = A 2 i f_i=A^{2^i} fi=A2i
然后倍增求特殊点权到特殊点权之间的时间,然后加上相应的权值
向量乘矩阵时间 O ( ( n w ) 2 ) O((nw)^2) O((nw)2)
总时间 O ( ( n w ) 3 l o g T + ( n w ) 2 k l o g T ) O((nw)^3\ logT\ +\ (nw)^2k\ logT) O((nw)3 logT + (nw)2k logT)
#include
#include
#include
#include
#define ll long long
#define p(x, y) ((x * 5) + (y))
using namespace std;
ll n, m, t, k, x, y, z, w, nn, now, pw[35], a[260], b[260];
struct matrix
{
ll a[260][260];
}f[35];
struct node
{
ll t, v, s;
}q[210];
bool cmp(node a, node b)
{
return a.t < b.t;
}
matrix jc(matrix &a)
{
matrix b;
memset(b.a, 0xcf, sizeof(b.a));
for (ll i = 0; i < nn; ++i)
for (ll j = 0; j < nn; ++j)
for (ll k = 0; k < nn; ++k)
b.a[i][j] = max(b.a[i][j], a.a[i][k] + a.a[k][j]);//矩阵乘矩阵
return b;
}
void js(matrix &b)
{
ll c[260];
memcpy(c, a, sizeof(a));
memset(a, 0xcf, sizeof(a));
for (ll i = 0; i < nn; ++i)
for (ll j = 0; j < nn; ++j)
a[j] = max(a[j], c[i] + b.a[i][j]);//向量乘矩阵
return;
}
void power(ll x)
{
for (ll i = 0; i <= w; ++i)
if (x&pw[i]) js(f[i]);
return;
}
int main()
{
scanf("%lld%lld%lld%lld", &n, &m, &t, &k);
nn = n * 5;
memset(f[0].a, 0xcf, sizeof(f[0].a));
for (ll i = 0; i < n; ++i)
{
scanf("%lld", &b[i]);
for (ll j = 1; j < 5; ++j)
f[0].a[p(i, j)][p(i, j - 1)] = 0;//拆分点
}
for (ll i = 1; i <= m; ++i)
{
scanf("%lld%lld%lld", &x, &y, &z);
x--;
y--;
f[0].a[p(x, 0)][p(y, z - 1)] = b[y];//连边
}
pw[0] = 1;
while(pw[w] * 2 <= t)
{
w++;
pw[w] = pw[w - 1] * 2;
f[w] = jc(f[w - 1]);//计算f
}
for (ll i = 1; i <= k; ++i)
scanf("%lld%lld%lld", &q[i].t, &q[i].v, &q[i].s), q[i].v--;
sort(q + 1, q + 1 + k, cmp);
q[++k] = (node){t, 0, 0};
memset(a, 0xcf, sizeof(a));
a[0] = b[0];
for (ll i = 1; i <= k; ++i)
{
power(q[i].t - now);//倍增
a[p(q[i].v, 0)] += q[i].s;
now = q[i].t;
}
if (a[0] < 0) printf("-1");
else printf("%lld", a[0]);
return 0;
}