bzoj 5415 归程

题目描述

本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定。 魔力之都可以抽象成一个 n 个节点、m 条边的无向连通图(节点的编号从 1 至 n)。我们依次用 l,a 描述一条边的长度、海拔。 作为季风气候的代表城市,魔力之都时常有雨水相伴,因此道路积水总是不可避免 的。由于整个城市的排水系统连通,因此有积水的边一定是海拔相对最低的一些边。我们用水位线来描述降雨的程度,它的意义是:所有海拔不超过水位线的边都是有积水的。

Yazid 是一名来自魔力之都的OIer,刚参加完ION2018 的他将踏上归程,回到他 温暖的家。 Yazid 的家恰好在魔力之都的 1 号节点。对于接下来 Q 天,每一天Yazid 都会告诉你他的出发点 v ,以及当天的水位线p。 每一天,Yazid 在出发点都拥有一辆车。这辆车由于一些故障不能经过有积水的边。 Yazid 可以在任意节点下车,这样接下来他就可以步行经过有积水的边。但车会被留在他下车的节点并不会再被使用。 需要特殊说明的是,第二天车会被重置,这意味着:

  • 车会在新的出发点被准备好。
  • Yazid 不能利用之前在某处停放的车。 Yazid 非常讨厌在雨天步行,因此他希望在完成回家这一目标的同时,最小化他步行经过的边的总长度。请你帮助 Yazid 进行计算。 本题的部分测试点将强制在线,具体细节请见【输入格式】和【子任务】。


输入

单个测试点中包含多组数据。输入的第一行为一个非负整数T,表示数据的组数。

接下来依次描述每组数据,对于每组数据:

第一行 2 个非负整数 n,m分别表示节点数、边数。

接下来 m 行,每行 4 个正整数u, v, l, a描述一条连接节点 u, v 的、长度为 l、海拔为 a 的边。 在这里,我们保证1u,vn。

接下来一行 3 个非负数 Q, K, S ,其中 Q 表示总天数,K0,1 是一个会在下面被用到的系数,S 表示的是可能的最高水位线。

接下来 Q 行依次描述每天的状况。每行 2 个整数 v0;p0 描述一天:
这一天的出发节点为v=(v0+K×lastans1)modn+1。
这一天的水位线为p=(p0+K×lastans)mod(S+1)。
其中 lastans 表示上一天的答案(最小步行总路程)。特别地,我们规定第 1 天时 lastans = 0。 在这里,我们保证1v0n,0p0S 。

对于输入中的每一行,如果该行包含多个数,则用单个空格将它们隔开。


输出

依次输出各组数据的答案。对于每组数据:

  • 输出 Q 行每行一个整数,依次表示每天的最小步行总路程。


样例输入

1
4 3
1 2 50 1
2 3 100 2
3 4 50 1
5 0 2
3 0
2 1
4 1
3 1
3 2


样例输出

0
50
200
50
150

 本题就是kruskal重构树, 按照水位建立最大生成树,然后答案都在子树里面。我们要先预处理1到每个点的最短距离,注意这题卡spfa,所以要用堆优化的dijkstra。 

预处理的子树的答案,然后用倍增的方法找到子树的根。  

ps:我的代码在bzoj和luogu都是过的,在loj死活re是什么鬼???

 

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<algorithm> 
  5 #include<cstring>
  6 #include<cmath>  
  7 #include<queue>  
  8 using namespace std;  
  9 int const N=200000+10;  
 10 int const M=400000+10;  
 11 int const inf=2000000000+10;  
 12 struct edge{
 13     int to,nt,w;    
 14 }e[M<<2];     
 15 struct E{
 16     int x,y,z,h;   
 17     bool operator < (const E & rhs) const{
 18         return h>rhs.h;  
 19     }
 20 }a[M];  
 21 struct node{
 22     int v,id;
 23     bool operator <(const node &rhs) const{
 24         return v>rhs.v;  
 25     }  
 26 };       
 27 priority_queue<node> q;
 28 int dist[N];    
 29 int cnt,h1[M],h2[M],val[M],vis[N],dp[M],fa[M][20],n,m,f[M];     
 30 void read(int &x){
 31     x=0; char c=getchar();  
 32     while (!isdigit(c)) c=getchar();  
 33     while (isdigit(c)) x=x*10+(c^48),c=getchar();  
 34 } 
 35 void add1(int a,int b,int c){
 36     e[++cnt]=(edge){b,h1[a],c};h1[a]=cnt;  
 37 }
 38 void add2(int a,int b){
 39     e[++cnt]=(edge){b,h2[a]}; h2[a]=cnt;  
 40 }
 41 int find(int x){
 42     return x==f[x]? x:f[x]=find(f[x]);       
 43 }
 44 void dijkstra(){
 45     memset(vis,0,sizeof(vis));  
 46     for(int i=1;i<=n;i++) dist[i]=inf;  
 47     dist[1]=0;q.push((node){0,1});  
 48     while (!q.empty()){
 49         int x=q.top().id; 
 50         q.pop();    
 51         if(vis[x]) continue;  
 52         vis[x]=1; 
 53         for(int i=h1[x];i;i=e[i].nt){
 54             int v=e[i].to;  
 55             if(dist[x]+e[i].w<dist[v]){
 56                 dist[v]=dist[x]+e[i].w;  
 57                 if(!vis[v]) 
 58                     q.push((node){dist[v],v});  
 59             }
 60         }
 61     }  
 62 }
 63 void kruscal(){
 64     sort(a+1,a+m+1);  
 65     for(int i=1;i<2*n;i++) f[i]=i; 
 66     int id=n;  
 67     for(int i=1;i<=m;i++){
 68         int fx=find(a[i].x);  
 69         int fy=find(a[i].y); 
 70         if(fx!=fy){
 71             id++;  
 72             val[id]=a[i].h;  
 73             f[fx]=f[fy]=id;  
 74             add2(id,fx);  
 75             add2(id,fy);  
 76             if (id==2*n-1) break;  
 77         }
 78     }
 79 }
 80 void dfs(int x){
 81     if(x<=n) dp[x]=dist[x]; 
 82     else dp[x]=inf;   
 83     for(int i=h2[x];i;i=e[i].nt){
 84         int v=e[i].to;  
 85         dfs(v);  
 86         fa[v][0]=x;  
 87         dp[x]=min(dp[x],dp[v]);  
 88     }  
 89 }
 90 int main(){ 
 91     int cas;  
 92     scanf("%d",&cas); 
 93     while (cas--){
 94         cnt=0;       
 95         memset(fa,0,sizeof(fa)); 
 96         memset(val,0,sizeof(val));    
 97         memset(h1,0,sizeof(h1));  
 98         memset(h2,0,sizeof(h2));  
 99         scanf("%d%d",&n,&m);  
100         for(int i=1;i<=m;i++){
101             scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].z,&a[i].h); 
102             add1(a[i].x,a[i].y,a[i].z);  
103             add1(a[i].y,a[i].x,a[i].z);   
104         }
105         dijkstra();  
106         kruscal(); 
107         for(int i=2*n-1;i>=1;i--)  
108             if(!fa[i][0]){
109                 fa[i][0]=i;
110                 dfs(i);  
111             }      
112         for(int j=1;j<=19;j++)  
113             for(int i=1;i<2*n;i++)  
114                 fa[i][j]=fa[fa[i][j-1]][j-1]; 
115         int last=0,q,k,s;  
116         scanf("%d%d%d",&q,&k,&s);    
117         while (q--){
118             int v,p;  
119             scanf("%d%d",&v,&p);  
120             v=(v+k*last-1)%n+1; 
121             p=(p+k*last)% (s+1); 
122             for(int i=19;i>=0;i--)  
123                 if(val[fa[v][i]]>p) v=fa[v][i];  
124             printf("%d\n",last=dp[v]);   
125         }
126     }
127     return 0;  
128 }
View Code

 

posted @ 2019-09-12 14:29  zjxxcn  阅读(136)  评论(0编辑  收藏  举报