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;
}
posted @ 2020-11-06 10:19  Point_King  阅读(98)  评论(0编辑  收藏  举报