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

大意: n结点有向有权图, m个操作, 增加若干边的权重或询问源点为1的单源最短路.

本题一个特殊点在于每次只增加边权, 并且边权增加值很小, 询问量也很小. 我们可以用johnson的思想, 转化为差值最短路, 这样边权就在n-1以内, 可以直接暴力跑桶优化dijkstra.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;


const int N = 1e5+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, q;
struct _ {int to,w;} E[N];
vector<int> g[N];
int vis[N], d2[N];
ll d[N];
priority_queue<pli,vector<pli>, greater<pli> > Q;
queue<int> q2[N];

void Dij() {
	memset(d,0x3f,sizeof d);
	Q.push(pli(d[1]=0,1));
	while (Q.size()) {
		int u = Q.top().y; Q.pop();
		if (vis[u]) continue;
		vis[u] = 1;
		for (auto &&id:g[u]) {
			auto &e = E[id];
			ll dd = d[u]+e.w;
			if (dd<d[e.to]) Q.push(pli(d[e.to]=dd,e.to));
		}
	}
}
void Dij2(int k) {
	REP(i,1,k) {int t; scanf("%d", &t), ++E[t].w;}
	memset(d2,0x3f,sizeof d2);
	q2[0].push(1), d2[1] = 0;
	int mx = 0;
	REP(i,0,mx) while (q2[i].size()) {
		int u = q2[i].front(); q2[i].pop();
		if (d2[u]<i) continue;
		for (auto &&id:g[u]) {
			auto &e = E[id];
			int dd = d2[u]+(e.w+d[u]-d[e.to]);
			if (dd<d2[e.to]) {
				d2[e.to] = dd;
				if (dd<=min(n-1,k)) { 
					q2[dd].push(e.to);
					mx = max(mx, dd);
				}
			}
		}
	}
	REP(i,1,n) d[i]=min(INF,d[i]+d2[i]);
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	REP(i,1,m) {
		int u;
		scanf("%d%d%d", &u, &E[i].to, &E[i].w);
		g[u].pb(i);
	}
	Dij();
	while (q--) {
		int op, x;
		scanf("%d%d", &op, &x);
		if (op==1) printf("%lld\n", d[x]<INF?d[x]:-1);
		else Dij2(x);
	}
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10628602.html