[LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程

题意

给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 \(v\) 和一个高度 \(h\), 鸭子德可以先无需花费地在高度大于 \(h\) 的边上任意行动, 然后可以在任意点开始以花费等于距离的模式行动. 问最小的花费.

\(|V|\le 2\times 10^5,|E|\le 4\times 10^5,q\le 4\times 10^5,h\le 10^9\).

题解

显然带花费部分的行动是一个单源最短路. 那么我们只要求出无花费部分的行动可以到达的点中哪一个点距离 \(1\) 最近就可以了.

发现无花费部分是个类似瓶颈路的问题, 我们可以在 Kruskal 重构树上倍增求出能到达的点所组成的子树, 输出这个子树中的点到 \(1\) 的最短距离就可以了.

为啥我要写这个裸题的题解呢?

一个原因是存板子, 另一个原因是这个沙雕强制在线把我卡掉了 \(3\) 分qaq...具体情况

参考代码

#include <bits/stdc++.h>

const int MAXV=4e5+10;
const int MAXE=1e6+10; struct Edge{
int from;
int to;
int dis;
int pos;
Edge* next;
bool friend operator>(const Edge& a,const Edge& b){
return a.pos>b.pos;
}
};
Edge E[MAXE];
Edge Ex[MAXE];
Edge* head[MAXV];
Edge* top=E; int v;
int e;
int q;
int n;
int k;
int maxv;
int dis[MAXV];
int pos[MAXV];
int ufs[MAXV];
bool vis[MAXV];
int pprt[20][MAXV];
int* prt=pprt[0]; int ReadInt();
void Kruskal();
int FindRoot(int);
void Dijkstra(int);
void Insert(int,int,int,int); int main(){
int T=ReadInt();
while(T--){
memset(pprt,0,sizeof(pprt));
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
top=E;
n=v=ReadInt();
e=ReadInt();
for(int i=0;i<e;i++){
int a=ReadInt(),b=ReadInt(),c=ReadInt(),d=ReadInt();
Ex[i]=Edge({a,b,c,d,NULL});
Insert(a,b,c,d);
Insert(b,a,c,d);
}
q=ReadInt(),k=ReadInt(),maxv=ReadInt();
Dijkstra(1);
Kruskal();
int lg=0;
for(int i=1;(1<<i)<=v;i++){
lg=i;
for(int j=1;j<=v;j++)
pprt[i][j]=pprt[i-1][pprt[i-1][j]];
}
int lastans=0;
while(q--){
int s=(0ll+ReadInt()+k*lastans-1)%n+1,h=(0ll+ReadInt()+k*lastans)%(maxv+1);
for(int i=lg;i>=0;i--){
if(pos[pprt[i][s]]>h)
s=pprt[i][s];
}
printf("%d\n",lastans=dis[s]);
}
}
return 0;
} void Kruskal(){
std::sort(Ex,Ex+e,std::greater<Edge>());
for(int i=1;i<=v;i++)
ufs[i]=i;
int& cur=v;
for(int i=0;i<e;i++){
int a=FindRoot(Ex[i].from);
int b=FindRoot(Ex[i].to);
if(a!=b){
++cur;
pos[cur]=Ex[i].pos;
dis[cur]=std::min(dis[a],dis[b]);
prt[a]=cur;
prt[b]=cur;
ufs[cur]=cur;
ufs[a]=cur;
ufs[b]=cur;
}
}
} void Dijkstra(int s){
std::priority_queue<std::pair<int,int>> q;
memset(dis,0x7F,sizeof(dis));
dis[s]=0;
q.emplace(0,s);
while(!q.empty()){
s=q.top().second;
q.pop();
if(vis[s])
continue;
vis[s]=true;
for(Edge* i=head[s];i!=NULL;i=i->next){
if(dis[i->to]>dis[s]+i->dis){
dis[i->to]=dis[s]+i->dis;
q.emplace(-dis[i->to],i->to);
}
}
}
} inline void Insert(int from,int to,int dis,int pos){
top->from=from;
top->to=to;
top->dis=dis;
top->pos=pos;
top->next=head[from];
head[from]=top++;
} int FindRoot(int x){
return ufs[x]==x?ufs[x]:ufs[x]=FindRoot(ufs[x]);
} inline int ReadInt(){
int x=0;
register char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return x;
}

最新文章

  1. tensorflow 学习笔记
  2. SQL Server 2008 收缩日志 清空删除大日志文件 转载
  3. format 字符串
  4. Linux Shell 数字计算与比较
  5. Eclipse vs IDEA快捷键对比大全(win系统)
  6. java线程condition
  7. Javascript—①你好,世界!
  8. String+ String.Concat String.Format StringBuilder 之间的性能测试
  9. JPA的一对多映射(双向)关联
  10. micropython TPYBoard v202 超声波测距
  11. Maven中遇到Unsupported major.minor version 51.0错误
  12. JS之iscroll.js的使用详解
  13. Socket网络编程--聊天程序(9)
  14. spring cloud ribbon源码解析(二)
  15. 如何利用JConsole观察分析JAVA程序的运行
  16. Leetcode 969. Pancake Sorting
  17. JS Number类型数字位数及IEEE754标准
  18. saltstack之软件管理
  19. How MapReduce Works(转)
  20. 2018 Multi-University Training Contest 1 H - RMQ Similar Sequence(HDU - 6305 笛卡尔树)

热门文章

  1. npm 命令 --save 和 --save-dev 的区别
  2. WIN10X64LTSC2019中度精简版by双心
  3. 2019csp-s
  4. python进阶之内存模型
  5. Net中的并发锁
  6. yii2关联表
  7. 【OCR技术系列之二】文字定位于切割
  8. SqlServer PIVOT行转列
  9. 反射2-spring boot jpa 注入model即实现查询
  10. Java实现Mysql的 substring_index 函数功能