题目链接

loj#2718. 「NOI2018」归程

题解

按照高度做克鲁斯卡尔重构树

那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离

spfa她死了...同步赛没写的说...

似乎前两题比去年简单些....连蒟蒻我都可做前两题的说

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9')c = getchar();
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
#define mp std::make_pair
#define pr std::pair<int,int>
int n,m;
const int maxn = 1000007;
struct node {
int u,v,a,l,next;
bool operator < (const node & A)const {
return a > A.a;
}
} edge[maxn << 1],e[maxn]; int num = 0,head[maxn],dis[maxn << 1];
inline void add_edge(int u,int v,int w) { edge[++ num].v = v;edge[num].l = w;edge[num].next = head[u];head[u] = num; }
std::priority_queue<pr> q;
void dijkstar() {
static bool vis[maxn];
memset(dis,0x3f,sizeof dis); memset(vis,0,sizeof vis);
dis[1] = 0;q.push(pr(0,1));
while(!q.empty()) {
int u = q.top().second;q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u];i;i = edge[i].next) {
int v = edge[i].v;
if(dis[v] > dis[u] + edge[i].l) dis[v] = dis[u] + edge[i].l,q.push(mp(-dis[v],v));
}
}
}
int fa[maxn];
int find(int x) { if(fa[x] != x) fa[x] = find(fa[x]); return fa[x]; }
int tot = 0,dad[maxn << 1][20],mn[maxn << 1];
int lastans = 0;
int query(int x,int p) {
for(int i = 18;i >= 0;-- i) {
if(mn[dad[x][i]] > p) x = dad[x][i];
}
return dis[x];
}
void solve() {
int Q = read(),k = read(),S = read(),v,p;
if(k) while(Q --) {
v = (read() + k * lastans - 1) % n + 1;
p = (read() + k * lastans ) % (S + 1);
printf("%d\n",lastans = query(v,p)); } else while(Q --) {
v = read(),p = read();
printf("%d\n",query(v,p));
}
}
void init() {
n = read(),m = read();
//int cnt = 0;
for(int u,v,a,l,i = 1;i <= m;++ i) {
u = read(),v = read(),l = read(),a = read();
e[i].u = u,e[i].v = v,e[i].a = a;
add_edge(u,v,l); add_edge(v,u,l);
}
dijkstar();
for(int i = 1;i <= n;++ i) fa[i] = i;
tot = n;
std::sort(e + 1,e + m + 1);
int k = 1;
for(int fx,fy,i = 1;i <= m;++ i) {
int x = e[i].u,y = e[i].v,h = e[i].a;
if((fx = find(x)) == (fy = find(y))) continue;
fa[fx] = fa[fy] = dad[fx][0] = dad[fy][0] = ++ tot; fa[tot] = dad[tot][0] = tot;
mn[tot] = e[i].a; dis[tot] = std::min(dis[fx],dis[fy]);
if(++ k == n)break;
}
/*for(int i = 1;i <= tot;++ i)
for(int j = 0;dad[i][j];++ j)
dad[i][j + 1] = dad[dad[i][j]][j],mn[i][j + 1] = std::min(mn[i][j],mn[dad[i][j]][j]);
*/
for(int i = 1;i <= 18;++ i)
for(int x = 1;x <= tot;++ x)dad[x][i] = dad[dad[x][i - 1]][i - 1];
solve();
}
int main() {
freopen("return.in","r",stdin); freopen("return.out","w",stdout);
int t = read();
while(t --) {
memset(head,0,sizeof head),num = 0; lastans = 0;
init();
}
return 0;
}

最新文章

  1. H5 meta小结
  2. 自动将指定目录下面的文件转换为UTF-8
  3. 定制Eclipse IDE之界面篇
  4. 蛋疼的Fedora17
  5. 【BZOJ】3456: 城市规划
  6. CNN 手写数字识别
  7. Gradient Boost Decision Tree(&amp;Treelink)
  8. Exception Handling Statements (C# Reference)
  9. 只要是从事IT,会些CSS,XHTML总归是有好处的
  10. java初学者必看经典
  11. POJ 2182 解题报告
  12. 机器学习基石 4 Feasibility of Learning
  13. 浏览器iscroll
  14. PHP----------file_get_content获取不到页面信息
  15. TLS协议工作过程;如何应用TLS/SSL协议为WEB流量提供安全
  16. Android-多线程AsyncTask
  17. December 01st 2016 Week 49th Thursday
  18. Oracle 9i &amp; 10g编程艺术-深入数据库体系结构-学习笔记(持续更新中)
  19. larave5.6 引入自定义函数库时,报错不能重复定义
  20. HttpServletRequest request方法详解

热门文章

  1. 编程语言BrainkFuck
  2. QByteArray储存二进制数据(包括结构体,自定义QT对象)
  3. μC/OS-Ⅱ在C8051F060上的移植及其应用
  4. Servlet笔记5--设置欢迎页面及HTTP状态码404、500
  5. Linux硬盘镜像获取与还原(dd、AccessData FTK Imager)
  6. Linux学习笔记-文件系统和基本命令
  7. html5新增表单元素
  8. python网络编程-协程(协程说明,greenlet,gevent)
  9. [java笔记]动态数组
  10. POJ 2195 Going Home(KM算法模板)