zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",g.dis[i]);
    //	printf("--------------
    ");
    	Kruskal::main(g,t);
    //	printf("--------------
    ");
    	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
    ",lstans);
    	}
    	return ;
    }
    int main()
    {
    	int T;cin>>T;
    	while(T--) solve();
    	return 0;
    }
    
  • 相关阅读:
    PHP保留小数的相关方法
    ASP.NET Core MVC 之过滤器(Filter)
    ASP.NET Core MVC 之控制器(Controller)
    ASP.NET Core MVC 之视图组件(View Component)
    ASP.NET Core MVC 之局部视图(Partial Views)
    标签助手(TagHelper)
    ASP.NET Core MVC 之布局(Layout)
    ASP.NET Core MVC 之视图(Views)
    ASP.NET Core MVC 之模型(Model)
    九卷读书:淘宝从小到大的发展 -重读《淘宝技术这十年》
  • 原文地址:https://www.cnblogs.com/Point-King/p/13935454.html
Copyright © 2011-2022 走看看