P4768 [NOI2018]归程
其实不是很想写题解的,但是由于我感觉我代码写的实在太漂亮了,决定记录一下。
其实会了重构树以后就感觉这是一道神笔题。
不多说了,代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=4e5+5;
struct Graph
{
int n,m;
struct Edge{int nxt,to,length,height;}e[M<<1];int fir[N];
void add(int u,int v,int w,int h,int i){e[i]=(Edge){fir[u],v,w,h},fir[u]=i;}
int dis[N];
void init(){memset(fir,0,sizeof(fir));}
}g;
struct Tree
{
int n;
struct Edge{int nxt,to;}e[N<<1];int fir[N<<1],size;
void add(int u,int v){e[++size]=(Edge){fir[u],v},fir[u]=size;}
struct Node{int fa[20],data,val;}tr[N<<1];//19
void init(){size=0,memset(fir,0,sizeof(fir));}
void work()
{
for(int i=1;i<=19;++i)
{
for(int j=1;j<=n;++j)
tr[j].fa[i]=tr[tr[j].fa[i-1]].fa[i-1];
}
}
int find(int u,int w)
{
for(int i=19;i>=0;--i)
{
if(tr[tr[u].fa[i]].val>w)
u=tr[u].fa[i];
}
return tr[u].data;
}
}t;
namespace Dijkstra
{
struct Data{int dis,id;};
bool operator < (const Data a,const Data b){return a.dis>b.dis;}
priority_queue<Data> q;
void main(Graph &g)
{
memset(g.dis,63,sizeof(g.dis));
g.dis[1]=0,q.push((Data){0,1});
while(!q.empty())
{
Data tmp=q.top();q.pop();
if(tmp.dis>g.dis[tmp.id]) continue;
for(int i=g.fir[tmp.id];i;i=g.e[i].nxt)
{
if(g.dis[g.e[i].to]>tmp.dis+g.e[i].length)
{
g.dis[g.e[i].to]=tmp.dis+g.e[i].length;
q.push((Data){g.dis[g.e[i].to],g.e[i].to});
}
}
}
}
}
namespace Kruskal
{
struct Edge{int from,to,val;}e[M];
bool cmp(Edge a,Edge b){return a.val>b.val;}
struct DSU
{
int fa[N];
void init(int n){for(int i=1;i<=n;++i)fa[i]=i;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(Edge e,Tree &t)
{
int fu=find(e.from),fv=find(e.to);
if(fu!=fv)
{
++t.n;
// printf("%d %d %d %d %d\n",fu,fv,t.n,t.tr[fu].data,t.tr[fv].data);
fa[fu]=fa[fv]=fa[t.n]=t.n;
t.add(t.n,fu),t.tr[fu].fa[0]=t.n;
t.add(t.n,fv),t.tr[fv].fa[0]=t.n;
t.tr[t.n].data=min(t.tr[fu].data,t.tr[fv].data);
t.tr[t.n].val=e.val;
}
}
}d;
void main(Graph &g,Tree &t)
{
for(int i=1;i<=g.m;++i)
{
e[i].from=g.e[i<<1].to;
e[i].to=g.e[i<<1|1].to;
e[i].val=g.e[i<<1].height;
}
sort(e+1,e+1+g.m,cmp);
t.n=g.n;d.init(g.n);
for(int i=1;i<=t.n;++i) t.tr[i].data=g.dis[i];
for(int i=1;i<=t.n;++i) t.tr[i].val=0;
for(int i=1;i<=g.m;++i) d.merge(e[i],t);
t.work();
}
}
void solve()
{
g.init(),t.init();
cin>>g.n>>g.m;
for(int i=1,u,v,w,h;i<=g.m;++i)
{
scanf("%d%d%d%d",&u,&v,&w,&h);
g.add(u,v,w,h,i<<1);
g.add(v,u,w,h,i<<1|1);
}
Dijkstra::main(g);
// for(int i=1;i<=g.n;++i) printf("%d\n",g.dis[i]);
// printf("--------------\n");
Kruskal::main(g,t);
// printf("--------------\n");
int q,k,s,u,w,lstans=0;
cin>>q>>k>>s;
while(q--)
{
scanf("%d%d",&u,&w);
u=(u+lstans*k-1)%g.n+1;
w=(w+k*lstans)%(s+1);
lstans=t.find(u,w);
printf("%d\n",lstans);
}
return ;
}
int main()
{
int T;cin>>T;
while(T--) solve();
return 0;
}