题目描述
本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定。 魔力之都可以抽象成一个 n 个节点、m 条边的无向连通图(节点的编号从 1 至 n)。 我们依次用 l,a 描述一条边的长度、海拔。 作为季风气候的代表城市,魔力之都时常有雨水相伴,因此道路积水总是不可避免 的。由于整个城市的排水系统连通,因此有积水的边一定是 海拔相对最低的一些边。 我们用水位线来描述降雨的程度,它的意义是:所有海拔不超过水位线的边都是有积水的。
Yazid 是一名来自魔力之都的 OIer,刚参加完 ION2018 的他将踏上归程,回到他 温暖的家。 Yazid 的家恰好在魔力之都的 1 号节点。对于接下来 Q 天,每一天 Yazid 都会告 诉你他的出发点 v ,以及当天的水位线 p。 每一天,Yazid 在出发点都拥有一辆 . 车。这辆车由于一些故障不能经过有积水的边。 Yazid 可以在任意节点下车,这样接下来他就可以步行经过有积水的边。但车会被留在 他下车的节点并不会再被使用。 • 需要特殊说明的是,第二天车会被重置,这意味着: – 车会在新的出发点被准备好。 – Yazid 不能利用之前在某处停放的车。 Yazid 非常讨厌在雨天步行,因此他希望在完成回家这一目标的同时,最小化他步行经过的边的总长度。请你帮助 Yazid 进行计算。 本题的部分测试点将强制在线,具体细节请见【输入格式】和【子任务】。
上面是题目描述。
主要做法kruscal重构树,即在kruscal合并的时候新建一个父节点,点权为原边权,这样可以形成一个大(小)根堆。
然后两个点求lca可知最大边最小(最小边最大)。具体看程序。
代码:
#include<queue> #include<cstdio> #include<algorithm> using namespace std; #define N 400005 #define M 800005 inline int rd() { int f=1,c=0;char ch = getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } struct Node { int u,v,l,a,nxt; }w[M],e[2*N]; struct Poi { int x,d; Poi(){} Poi(int x,int d):x(x),d(d){} friend bool operator < (Poi a,Poi b) { return a.d>b.d; } }; bool cmp(Node n1,Node n2) { return n1.a>n2.a; } int T,n,m,ans,cnt,hed[N],q,k,s; void ae(int f,int t,int l) { e[++cnt].u = f; e[cnt].v = t; e[cnt].l=l; e[cnt].nxt = hed[f]; hed[f]=cnt; } int dis[N]; bool vis[N]; priority_queue<Poi>que; void dij() { for(int i=1;i<=n;i++) { dis[i]=0x3f3f3f3f; vis[i]=0; } dis[1]=0; que.push(Poi(1,0)); while(!que.empty()) { Poi tp = que.top(); que.pop(); int u = tp.x; if(vis[u])continue; vis[u]=1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].v; if(dis[to]>dis[u]+e[j].l) { dis[to]=dis[u]+e[j].l; que.push(Poi(to,dis[to])); } } } } int fa[2*N][22],ff[2*N],vl[2*N],min_dis[2*N],tot; int findfa(int x) { return ff[x]==x?x:ff[x]=findfa(ff[x]); } void kruskal() { int ad = 0; tot = n; for(int i=1;i<=n;i++) { min_dis[i]=dis[i]; ff[i]=i; } for(int i=1;ad<n-1;i++) { int u = w[i].u; int v = w[i].v; if(findfa(u)!=findfa(v)) { ad++; tot++; fa[ff[u]][0]=tot; fa[ff[v]][0]=tot; min_dis[tot]=min(min_dis[ff[u]],min_dis[ff[v]]); vl[tot]=w[i].a; ff[tot]=tot; ff[ff[u]]=tot; ff[ff[v]]=tot; } } } int main() { T=rd(); while(T--) { n=rd(),m=rd(),ans=0; for(int i=1;i<=n;i++)hed[i]=0; cnt=0; for(int i=1;i<=m;i++) { w[i].u=rd(),w[i].v=rd(),w[i].l=rd(),w[i].a=rd(); ae(w[i].u,w[i].v,w[i].l); ae(w[i].v,w[i].u,w[i].l); } dij(); sort(w+1,w+1+m,cmp); kruskal(); for(int j=1;j<=20;j++) { for(int i=1;i<=tot;i++) { fa[i][j]=fa[fa[i][j-1]][j-1]; } } q=rd(),k=rd(),s=rd(); int v,p; for(int i=1;i<=q;i++) { v = (rd()+k*ans-1)%n+1; p = (rd()+k*ans)%(s+1); ans=dis[v]; for(int j=20;j>=0;j--) { if(vl[fa[v][j]]>p) { ans=min_dis[fa[v][j]]; v=fa[v][j]; } } printf("%d ",ans); } } return 0; }