给你一个有向无环图,QQQ次询问,每次问111到kkk是否有一条路径长度sss满足k≤s≤1.1×kk\leq s\leq1.1\times kk≤s≤1.1×k。
如果直接暴力背包,是得不到满分的,好像空间也存不下,考虑如何优化?哪些点存下来是没有必要的呢?考虑这种情况:11.1x≤y≤x\frac{1}{1.1}x\leq y\leq x1.11x≤y≤x,这种情况下yyy是没有存在的必要的。所以我们不必存它。
所以就可以直接拓扑,然后归并答案,对于每个询问直接暴力扫也是可以的。因为按照上述方法存点差不多每个点只会存400400400个值。
code:code:code:
#include <bits/stdc++.h>
#define int long long
#define regi register int
int n,m,q;
int in[200001];
long long f[200001][401];
int Tot[200001];
int head[500001],tot;
long long temp[200001];
std::queue<int>Q;
struct edge{
int to;
int nxt;
int w;
}e[1000001];
inline int read(){
int r=0,w=0,c;
for(;!isdigit(c=getchar());r=c);
for(w=c^48;isdigit(c=getchar());w=w*10+(c^48));
return r^45?w:-w;
}
inline void add(int x,int y,int z){
e[++tot]={y,head[x],z};head[x]=tot;
}
inline long long calc(long long x){
return x*11/10;
}
inline void merge(int x,int y,int z){
if(!Tot[x]&&!Tot[y])
return;
regi i=1,j=1,tail=0;
while(i<=Tot[x]&&j<=Tot[y])
if(f[x][i]+z<=f[y][j])
temp[++tail]=f[x][i++]+z;
else
temp[++tail]=f[y][j++];
while(i<=Tot[x])
temp[++tail]=f[x][i++]+z;
while(j<=Tot[y])
temp[++tail]=f[y][j++];
f[y][Tot[y]=1]=temp[1];
f[y][0]=0;
for(regi i=2;i<=tail;++i)
if(temp[i]<=calc(f[y][Tot[y]-1]))
f[y][Tot[y]]=temp[i];
else
f[y][++Tot[y]]=temp[i];
}
main(){
n=read(),m=read(),q=read();
for(regi i=1,x,y,z;i<=m;++i){
x=read(),y=read(),z=read();
add(x,y,z);
in[y]++;
}
Tot[1]=1;
f[1][1]=0;
for(regi i=1;i<=n;++i)
if(!in[i])
Q.push(i);
while(!Q.empty()){
regi x=Q.front();
Q.pop();
for(regi i=head[x];i;i=e[i].nxt){
regi y=e[i].to;
regi z=e[i].w;
merge(x,y,z);
if(!--in[y])
Q.push(y);
}
}
while(q--){
regi x=read(),y=read();
bool flag=0;
for(regi i=1;i<=Tot[x];++i)
flag|=(y<=f[x][i]&&calc(y)>=f[x][i]);
flag?puts("YES"):puts("NO");
}
return 0;
}