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;
    }
    
  • 相关阅读:
    ASP.NET 分页数据源:: PagedDataSource //可分页数据源
    strtok
    FloydWarshall算法详解(转)
    Tom Clancy's Splinter Cell: Double Agent
    暴雪COO确认:星际争霸2.0要来了
    wxWidgets 2.8.0 released
    如饥似渴
    大乘法器遇见小乘法器
    GLEW 1.3.5 adds OpenGL 2.1 and NVIDIA G80 extensions
    DevIL真是好用得想哭
  • 原文地址:https://www.cnblogs.com/Point-King/p/13935454.html
Copyright © 2011-2022 走看看