归程题解

归程题解

不知道我是看错了还是咋的,

步行可以走没有积水的边,

这样接下来他就可以步行经过有积水的边

我看到这一句话,总以为只能走有积水的边,
又屈辱看题解
咳咳,使步行总长最小,我们可以考虑预处理出每个点到1的最短路,
看看车子通过没积水的边能到哪些点,输出最小值,
这怎么搞?
来一波Kruskal重构树,
没学过的可以看我的这篇博客
已知,能走到最上面的点,它的子树就都能走到
我们可以搜索出子树内最小的最短路,然后倍增,看最多能走到哪个点,输出。
代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
using namespace std;
const int N=2e5+6,M=4e5+6;
int n,m,t,Q,K,S,cnt=0,num=0,tot=0;
int cnt2=0,head2[N<<1],fa[N<<1],head[N],tt;
int f[N<<1][21],g[N<<1][21];
ll dis[N<<1],mind[N<<1],t1,t2,ans=0;
struct edge{int nxt,to,w;}e[M<<1],gg[M<<1];
struct xd{
   int i; ll z;
   bool operator < (const xd &a) const {return z>a.z;}
}tmp,nw;
struct que{int x,y,z;}qu[M];
priority_queue<xd> q;
inline void add(int u,int v,int w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,head[u]=cnt;}
inline void add2(int u,int v,int w){gg[++cnt2].nxt=head2[u],gg[cnt2].to=v,gg[cnt2].w=w,head2[u]=cnt2;}
void dijkstra(){
	memset(dis,0x3f,sizeof(dis)),tmp.i=1,tmp.z=0,dis[1]=0,q.push(tmp);
	while(!q.empty()){
		tmp=q.top(),q.pop(); //cout<<tmp.i<<" "<<tmp.z<<endl;
		if(dis[tmp.i]<tmp.z) continue;
		for(int i=head[tmp.i];i;i=e[i].nxt){
			nw.i=e[i].to,nw.z=tmp.z+e[i].w;
			if(dis[nw.i]>nw.z) dis[nw.i]=nw.z,q.push(nw);
		}
	}
	//for(int i=1;i<=n;++i) printf("%d %lld\n",i,dis[i]);
}
inline int read(){
	int T=0,F=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
	return F*T;
}
bool cmp(que u,que v){return u.z>v.z;}
int getf(int x){return fa[x]==x?x:fa[x]=getf(fa[x]);}
bool merge(int x,int y,int z){
     x=getf(x),y=getf(y);
     if(x==y) return false;
     ++tot,f[x][0]=tot,f[y][0]=tot,g[x][0]=z,g[y][0]=z,fa[x]=fa[y]=fa[tot]=tot,add2(tot,x,z),add2(tot,y,z);
     return true;	
}
void dfs(int x){
    mind[x]=dis[x];
    for(int i=1;i<=20;++i) f[x][i]=f[f[x][i-1]][i-1],g[x][i]=min(g[x][i-1],g[f[x][i-1]][i-1]); 
    for(int i=head2[x];i;i=gg[i].nxt) dfs(gg[i].to),mind[x]=min(mind[x],mind[gg[i].to]);  
}
int main(){
	tt=read();
	while(tt--){
	   n=read(),m=read(),cnt=0,cnt2=0,num=0,ans=0,tot=n,memset(dis,0x3f,sizeof(dis)),memset(head,0,sizeof(head)),memset(head2,0,sizeof(head2)),memset(g,0,sizeof(g)),memset(f,0,sizeof(f));
     	for(int i=1;i<=n;++i) fa[i]=i;
	   for(int i=1;i<=m;++i) qu[i].x=read(),qu[i].y=read(),t=read(),qu[i].z=read(),add(qu[i].x,qu[i].y,t),add(qu[i].y,qu[i].x,t);
	   sort(qu+1,qu+m+1,cmp),dijkstra();
	   for(int i=1;i<n;++i){
	       ++num;
	       if(num>m) break;
	       if(!merge(qu[num].x,qu[num].y,qu[num].z)) --i;
   	} 
    	dfs(tot),Q=read(),K=read(),S=read()+1;
   	for(int i=1;i<=Q;++i){
	       t1=read(),t2=read(),t1=(t1+ans*K-1)%n+1,t2=(t2+ans*K)%S;
	       for(int j=20;j>=0;--j) if(f[t1][j]&&t2<g[t1][j]) t1=f[t1][j];
	       ans=mind[t1],printf("%lld\n",ans);
	   }  
	}   
	return 0;
}
posted @ 2019-10-21 20:11  lsoi_ljk123  阅读(150)  评论(0编辑  收藏  举报