题链:https://loj.ac/problem/2718
由于有无积水对行走没有影响,所以先预处理出每个点到1号点的路径
问题就变成了求一个联通块中最小值
两种方法:
1、用可持久化并查集维护,在根节点记录最小值
2、用kruskal重构树维护,用ST表维护最小值
方法1代码:
#include
#include
#include
using namespace std;
const int N=2e6+5,M=2e7+5;;
struct A{ int fa,r,v; }c[M];
int n,m,r[N],ls[M],rs[M],rt[N],ans;
int cnt,to[N],nxt[N],he[N],dis[N],w[N],rtw[N];
bool fl[N];
struct B{int id,x;};
bool operator >(B i,B j){return i.x>j.x; }
priority_queue,greater >q;
struct C{int u,v,h; }e[N];
bool cmp(C i,C j){return i.h>j.h;}
void write(int x)
{
if(x/10) write(x/10);
putchar(x%10+48);
}
inline int read()
{
int ret=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
{
ret=(ret<<1)+(ret<<3)+ch-'0';
ch=getchar();
}
return ret;
}
void build(int &p,int l,int r)
{
p=++cnt;
if(l==r)
{
c[p]=(A){l,0,dis[l]};
return;
}
int mid=l+r>>1;
build(ls[p],l,mid);
build(rs[p],mid+1,r);
}
A get(int p,int l,int r,int x)
{
if(l==r)
return c[p];
int mid=l+r>>1;
if(x<=mid)
return get(ls[p],l,mid,x);
else
return get(rs[p],mid+1,r,x);
}
void update(int p1,int &p2,int l,int r,int x,A y)
{
ls[++cnt]=ls[p1];
rs[cnt]=rs[p1];
p2=cnt;
if(l==r)
{
c[p2]=y;
return;
}
int mid=l+r>>1;
if(x<=mid)
update(ls[p1],ls[p2],l,mid,x,y);
else
update(rs[p1],rs[p2],mid+1,r,x,y);
}
A find(int root,int u)
{
A x=get(root,1,n,u);
return u==x.fa?x:find(root,x.fa);
}
inline void add(int u,int v,int k)
{
to[++cnt]=v;
nxt[cnt]=he[u];
w[cnt]=k;
he[u]=cnt;
}
int findr(int x)
{
int l=1,r=n-1,ans=0;
while(l<=r)
{
int mid=l+r>>1;
if(rtw[mid]>=x)
{
ans=mid;
l=mid+1;
}else
r=mid-1;
}
return ans;
}
int main()
{
freopen("return.in","r",stdin); //这道题一定要文件输入输出,否则TLE
freopen("return.out","w",stdout);
int T=read();
while(T--)
{
n=read(),m=read();
for(int i=1;i<=n;i++)
he[i]=0;
cnt=0;
for(int i=1;i<=m;i++)
{
e[i].u=read(),e[i].v=read();
int k=read();
e[i].h=read();
add(e[i].u,e[i].v,k);
add(e[i].v,e[i].u,k);
}
for(int i=1;i<=n;i++)
{
dis[i]=1e9;
fl[i]=0;
}
while(!q.empty()) q.pop();
q.push((B){1,dis[1]=0});
for(int i=1;i<=n;i++)
{
while(fl[q.top().id]) q.pop();
int u=q.top().id;
fl[u]=1;
for(int E=he[u];E;E=nxt[E])
{
int v=to[E];
if(!fl[v]&&dis[v]>dis[u]+w[E])
q.push((B){v,dis[v]=dis[u]+w[E]});
}
}
sort(e+1,e+m+1,cmp);
cnt=0;
build(rt[0],1,n);
int tot=0;
for(int i=1;i<=m;i++)
{
A u=find(rt[tot],e[i].u),v=find(rt[tot],e[i].v);
if(u.fa!=v.fa)
{
++tot;
rt[tot]=rt[tot-1];
rtw[tot]=e[i].h;
if(u.r>v.r)
{
update(rt[tot-1],rt[tot],1,n,v.fa,(A){u.fa,v.r,v.v});
update(rt[tot],rt[tot],1,n,u.fa,(A){u.fa,u.r,min(u.v,v.v)});
}
else
if(u.r==v.r)
{
update(rt[tot-1],rt[tot],1,n,u.fa,(A){v.fa,u.r,u.v});
update(rt[tot],rt[tot],1,n,v.fa,(A){v.fa,v.r+1,min(u.v,v.v)});
}
else
{
update(rt[tot-1],rt[tot],1,n,u.fa,(A){v.fa,u.r,u.v});
update(rt[tot],rt[tot],1,n,v.fa,(A){v.fa,v.r,min(u.v,v.v)});
}
if(tot==n-1) break;
}
}
int q=read(),K=read(),S=read();
ans=0;
while(q--)
{
int v=(read()+K*ans-1)%n+1,p=(read()+K*ans)%(S+1);
int edi=findr(p+1);
write(ans=find(rt[edi],v).v),puts("");
}
for(int i=1;i<=cnt;i++)
{
ls[i]=0;
rs[i]=0;
}
}
return 0;
}
方法2:
#include
#include
#include
using namespace std;
const int N=1e6+5;
int n,m,ans,tot,dfn,in[N],out[N],dy[N];
int fa[N],fi[N][20],fw[N][20],son[N][2];
int cnt,to[N],nxt[N],he[N],dis[N],w[N];
int lg[N],f[N][20];
bool fl[N];
struct B{int id,x;};
bool operator >(B i,B j){return i.x>j.x; }
priority_queue,greater >q;
struct C{int u,v,h; }e[N];
bool cmp(C i,C j){return i.h>j.h;}
void write(int x)
{
if(x/10) write(x/10);
putchar(x%10+48);
}
inline int read()
{
int ret=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
{
ret=(ret<<1)+(ret<<3)+ch-'0';
ch=getchar();
}
return ret;
}
inline void add(int u,int v,int k)
{
to[++cnt]=v;
nxt[cnt]=he[u];
w[cnt]=k;
he[u]=cnt;
}
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void dfs(int u)
{
if(u<=n)
{
dfn++;
in[u]=out[u]=dfn;
dy[dfn]=u;
return;
}
dfs(son[u][0]);
dfs(son[u][1]);
in[u]=in[son[u][0]];
out[u]=out[son[u][1]];
}
inline int get(int l,int r)
{
int k=lg[r-l+1];
return min(f[l][k],f[r-(1<>1]+1;
while(T--)
{
n=read(),m=read();
for(int i=1;i<=n;i++)
he[i]=0;
cnt=0;
for(int i=1;i<=m;i++)
{
e[i].u=read(),e[i].v=read();
int k=read();
e[i].h=read();
add(e[i].u,e[i].v,k);
add(e[i].v,e[i].u,k);
}
for(int i=1;i<=n;i++)
{
dis[i]=1e9;
fl[i]=0;
}
while(!q.empty()) q.pop();
q.push((B){1,dis[1]=0});
for(int i=1;i<=n;i++)
{
while(fl[q.top().id]) q.pop();
int u=q.top().id;
fl[u]=1;
for(int E=he[u];E;E=nxt[E])
{
int v=to[E];
if(!fl[v]&&dis[v]>dis[u]+w[E])
q.push((B){v,dis[v]=dis[u]+w[E]});
}
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n+n-1;i++)
fa[i]=i;
tot=n;
for(int i=1;i<=m;i++)
{
int u=find(e[i].u),v=find(e[i].v);
if(u!=v)
{
tot++;
fa[u]=tot;
fa[v]=tot;
fi[u][0]=tot;
fw[u][0]=e[i].h;
fi[v][0]=tot;
fw[v][0]=e[i].h;
fw[tot][0]=e[i].h;
son[tot][0]=u;
son[tot][1]=v;
if(tot==n+n-1) break;
}
}
fi[tot][0]=tot;
for(int j=1;j<=lg[tot];j++)
for(int i=1;i<=tot;i++)
{
fi[i][j]=fi[fi[i][j-1]][j-1];
fw[i][j]=min(fw[i][j-1],fw[fi[i][j-1]][j-1]);
}
dfn=0;
dfs(tot);
for(int i=1;i<=n;i++)
f[i][0]=dis[dy[i]];
for(int j=1;j<=lg[n];j++)
for(int i=1;i<=n-(1<=0;i--)
if(fw[v][i]>=p+1)
v=fi[v][i];
ans=get(in[v],out[v]);
write(ans),puts("");
}
}
return 0;
}