[ZROJ-961]路徑長度 Solution

給你一個有向無環圖,QQ次詢問,每次問11kk是否有一條路徑長度ss滿足ks1.1×kk\leq s\leq1.1\times k
如果直接暴力揹包,是得不到滿分的,好像空間也存不下,考慮如何優化?哪些點存下來是沒有必要的呢?考慮這種情況:11.1xyx\frac{1}{1.1}x\leq y\leq x,這種情況下yy是沒有存在的必要的。所以我們不必存它。
所以就可以直接拓撲,然後歸併答案,對於每個詢問直接暴力掃也是可以的。因爲按照上述方法存點差不多每個點只會存400400個值。
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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章