前言
如果你毫无思路,考虑暴力!然后优化它!
题目
讲解
如果你想容斥,那么你已经没救了。
( t Floyd) 应该不用讲吧。
我们先想暴力,枚举一条边,然后在三元组里面检验,时间复杂度是 (O(mq)=O(n^4))。
我们发现枚举边似乎不是很能优化,于是我们考虑是否能够不枚举三元组。
我们把一条边是好边的条件写下来:存在一个三元组 (l_{i,j}ge dis_{i,u}+w_{u,v}+dis_{v,j})。
移项: (l_{i,j}-dis_{i,u}ge w_{u,v}+dis_{v,j})。
我们发现 (RHS) 已经和 (i) 无关,可以 (O(nm)) 做,这时我们只需要知道 (LHS) 即可。
记 (LHS) 最大值为 (MAX_{j,u}),显然可以用 (O(qn)) 的时间复杂度预处理,注意一个三元组中的 (l) 既可以代表 (l_{i,j}) 也可以代表 (l_{j,i})。
此时时间复杂度已经降为了 (O(n^3)) 级别。
代码
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read(); m = Read();
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n;++ j)
if(i ^ j) dis[i][j] = INF;
for(int i = 1;i <= m;++ i)
{
u[i] = Read(),v[i] = Read(),w[i] = Read();
dis[u[i]][v[i]] = dis[v[i]][u[i]] = w[i];
}
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]);
for(int Q = Read(); Q ;-- Q)
{
int i = Read(),j = Read(),l = Read();
for(int u = 1;u <= n;++ u) MAX[j][u] = Max(MAX[j][u],l-dis[i][u]),MAX[i][u] = Max(MAX[i][u],l-dis[j][u]);
}
for(int i = 1;i <= m;++ i)
for(int j = 1;j <= n;++ j)
if(MAX[j][u[i]] >= w[i]+dis[v[i]][j])
{
ans++;
break;
}
Put(ans);
return 0;
}