[CF843D]Dynamic Shortest Path

题目大意:

给定一个带权有向图,包含\(n(n\le10^5)\)个点和\(m(m\le10^5)\)条边。共\(q(q\le2000)\)次操作,操作包含以下两种:

  • \(1\:v\)——查询从\(1\)到\(v\)的最短路。
  • \(2\:c\:l_1\:l_2\:\ldots\:l_c\)——将边\(l_1,l_2,\ldots,l_c\)增加\(1\)的权值。

思路:

首先使用Dijkstra算法求出原图的单源最短路径\(dis[i]\)。对于所有的操作\(2\),考虑增加边权后对答案的影响。不难发现每次修改边权后\(dis[i]\)都会增加一定量或保持不变。不妨将每次每个点的增加量记作\(add[i]\),考虑增加边权后计算\(add[i]\)的值。

类比Dijkstra算法的“松弛”操作,对于一个结点\(x\),若\(add[x]\ne0\),我们可以用\(x\)来松弛别的结点。枚举\(x\)的下一个结点\(y\),若此时用\(x\)作为最短路中的上一任结点,则最短路长度需要增加\(dis[x]+w(x,y)+add[x]-dis[y]\)。而\(add[y]\)则需要对所有这样的值取\(\min\)。这样完成所有的松弛操作后,\(dis'[i]=dis[i]+add[i]\)。而这可以用BFS实现,其中当\(add[i]>c\)时则没有“松弛”的必要,可以进行剪枝。

配对堆优化Dijkstra复杂度\(\mathcal O(n\log n+m)\),单次BFS更新最短路\(\mathcal O(q(n+m))\),总时间复杂度\(\mathcal O(n\log n+m+q(n+m))\)。

细节:

注意边权可能为\(0\),因此Dijkstra中被松弛的结点可能会跑到堆顶,不能松弛完再删除堆顶元素。本题时间限制较紧,实现时注意优化常数。

源代码:

#include<queue>
#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
#include<functional>
#include<forward_list>
#include<ext/pb_ds/priority_queue.hpp>
using int64=long long;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
constexpr int N=1e5+1;
int n,w[N],add[N];
int64 dis[N];
using Edge=std::pair<int,int>;
std::forward_list<Edge> e[N];
using Vertex=std::pair<int64,int>;
__gnu_pbds::priority_queue<Vertex,std::greater<Vertex>> q;
__gnu_pbds::priority_queue<Vertex,std::greater<Vertex>>::point_iterator p[N];
inline void dijkstra() {
for(register int i=1;i<=n;i++) {
p[i]=q.push({dis[i]=i==1?0:LLONG_MAX,i});
}
while(!q.empty()&&q.top().first!=LLONG_MAX) {
const int x=q.top().second;
q.pop();
for(register auto &j:e[x]) {
const int &y=j.first,&w=::w[j.second];
if(dis[x]+w<dis[y]) {
q.modify(p[y],{dis[y]=dis[x]+w,y});
}
}
}
q.clear();
}
std::queue<int> v[N];
int main() {
n=getint();
const int m=getint(),q=getint();
for(register int i=1;i<=m;i++) {
const int u=getint(),v=getint();
w[i]=getint();
e[u].emplace_front(std::make_pair(v,i));
}
dijkstra();
for(register int i=1;i<=n;i++) {
if(dis[i]==LLONG_MAX) dis[i]=-1;
}
for(register int i=0;i<q;i++) {
if(getint()==1) {
printf("%lld\n",dis[getint()]);
} else {
const int c=getint();
for(register int i=0;i<c;i++) w[getint()]++;
std::fill(&add[1],&add[n]+1,c+1);
v[add[1]=0].emplace(1);
for(register int i=0;i<=c;i++) {
for(;!v[i].empty();v[i].pop()) {
const int &x=v[i].front();
if(add[x]!=i) continue;
for(register auto &j:e[x]) {
const int &y=j.first,&w=::w[j.second];
const int64 d=dis[x]+w+add[x]-dis[y];
if(d<add[y]) v[add[y]=d].emplace(y);
}
}
}
for(register int i=1;i<=n;i++) {
if(add[i]!=c+1) dis[i]+=add[i];
}
}
}
return 0;
}

[CF843D]Dynamic Shortest Path的更多相关文章

  1. CF843D Dynamic Shortest Path spfa+剪枝

    考试的T3,拿暴力+剪枝卡过去了. 没想到 CF 上也能过 ~ code: #include <bits/stdc++.h> #define N 100004 #define LL lon ...

  2. Dynamic Shortest Path CodeForces - 843D (动态最短路)

    大意: n结点有向有权图, m个操作, 增加若干边的权重或询问源点为1的单源最短路. 本题一个特殊点在于每次只增加边权, 并且边权增加值很小, 询问量也很小. 我们可以用johnson的思想, 转化为 ...

  3. cf 843 D Dynamic Shortest Path [最短路+bfs]

    题面: 传送门 思路: 真·动态最短路 但是因为每次只加1 所以可以每一次修改操作的时候使用距离分层的bfs,在O(n)的时间内解决修改 这里要用到一个小技巧: 把每条边(u,v)的边权表示为dis[ ...

  4. Method for finding shortest path to destination in traffic network using Dijkstra algorithm or Floyd-warshall algorithm

    A method is presented for finding a shortest path from a starting place to a destination place in a ...

  5. [LeetCode] 847. Shortest Path Visiting All Nodes 访问所有结点的最短路径

    An undirected, connected graph of N nodes (labeled 0, 1, 2, ..., N-1) is given as graph. graph.lengt ...

  6. 干货 | 列生成VRPTW子问题ESPPRC( Elementary shortest path problem with resource constraints)介绍附C++代码

    00 前言 各位小伙伴大家好,相信大家已经看过前面column generation求解vehicle routing problems的过程详解.该问题中,子问题主要是找到一条reduced cos ...

  7. hdu-----(2807)The Shortest Path(矩阵+Floyd)

    The Shortest Path Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. zoj 2760 How Many Shortest Path 最大流

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 Given a weighted directed graph ...

  9. The Shortest Path in Nya Graph

    Problem Description This is a very easy problem, your task is just calculate el camino mas corto en ...

随机推荐

  1. js 作用域链&内存回收&变量&闭包

    闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等 一.作用域链:函数在定义的时候创建的,用于寻找使用到的变量的值的一个索引,而他内部的规则是,把函数自身的本地变量放在 ...

  2. CentOS7修改默认运行级别

    新装了一个虚拟机,图形界面启动太慢,想调整一下按照以前的经验改运行级别,输入: vi /etc/inittab 然后发现跟之前不一样了,在inittab设置不再生效: # inittab is no ...

  3. 调试应用程序(Debugging Applications)

    调试应用程序(Debugging Applications)¶ Phalcon中提供了提供了几种调试级别即通知,错误和异常. 异常类 Exception class 提供了错误发生时的一些常用的调试信 ...

  4. C++之初始化问题

    首先,我们应该明确的是在C++中初始化不是赋值,因为初始化是必要的,如果读取了未初始化的值将会导致不明确的行为.初始化指创建变量并且给它赋初值,而赋值则是擦除对象的当前值并用新值代替.C++支持两种初 ...

  5. HDU 5118 GRE Words Once More!

    题目链接:HDU-5118 题意:给定一个有向无环图,每条边有一个权值.标定一些特定节点为“特殊节点”.从节点1出发到某“特殊节点”结束的路径,称为一个“GRE单词”.单词由路径上的权值组成.给定一组 ...

  6. C基础 内存统一入口

    引言  - malloc 引述 C标准中堆上内存入口就只有 malloc, calloc, realloc . 内存回收口是 free. 常见的一种写法是 struct person * per = ...

  7. popup menu案例,无说明只代码

    效果图: 布局文件, 展示列表的容器 <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...

  8. ora11g listener.ora

    配置内容方式1: LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = IPC) (KEY = EXTPROC152 ...

  9. django “如何”系列10:如何管理静态文件

    django开发者最关心的是web应用中的动态部分-视图函数和模板.但是明显,web应用还有其他需要注意的部分:静态文件(图片,css,javascript等等),那些都是渲染一个完整的页面需要的东西 ...

  10. 属性名、变量名与 内部关键字 重名 加&

    procedure TForm4.btn3Click(Sender: TObject); var MyQj: TQJson; MyPrinter: TPrinter; begin MyQj := TQ ...