CF843D-Dynamic-ShortestPath(动态最短路)

Posted wmq12138

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF843D-Dynamic-ShortestPath(动态最短路)相关的知识,希望对你有一定的参考价值。

动态最短路:CF843D Dynamic Shortest Path

题意:
有一张(n)个点(m)条边的有向带权图,(q)次询问:

1 (1 v) 询问从(1)(v)的最短路,无解输-(1)

2 (c l_1 l_2 ... l_c l_i)的边权增加(1)

(q leqslant 2000 n,m leqslant 10^5)

题解:

暴力(dij)显然过不了,需要优化

首先我们知道一种(dij)的优化方法:
保证边权都为正,且边权和不超过(W)的时候

性质:如果用 (??) 更新周围的点 (??) 的最短路,那么
源到 (t) 的最短路长度一定大于到 (??) 的最短路长度。

(0)~(W) 的(桶)队列代替堆

从小到大枚举值来取出当前最小值。根据性质,加
入的元素一定只会加到当前枚举的这个值的后面。

复杂度(O(m+W)),现在我们要尽量缩小值域就可以优化了

先做一遍正常(dij),然后考虑该边若干条边造成的影响

令每条边((x,y))的边权为(dis[x]+edge[i]-dis[y]),

假设这样求出来的最短路为(f[x]),则(f[x])表示新图中此点的距离较原图的增量

分析(f[x])的值域:一次更新(c)条边,则最短路最多增加(c)(n)个点的最短路共经过(n-1)条边,
则最短路增加不超过(n-1),而(n)的范围是(10^5),就可以接受了,总共复杂度(O(q(m+W)))

//CF843D-Dynamic-ShortestPath
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <queue>
using namespace std;

typedef long long LL;
#define cls(x) memset(x,0,sizeof(x))
#define For(i,j,k) for(register int i=(j);i<=(k);++i)
#define Rep(i,j,k) for(register int i=(j);i>=(k);--i)
#define rint register int
#define il inline

il int read(int x=0,int f=1,char ch='0')
{
    while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return f*x;
}

const int N=1e5+5;
int head[N],ver[N],nxt[N],edge[N];
int n,m,Q,tot;
LL d[N],f[N],t; bool v[N];
il void add(int x,int y,int z)
{ ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; edge[tot]=z; }

il void dij()
{
    priority_queue<pair<LL,int> > q; 
    memset(d,0x3f,sizeof(d)); d[1]=0;
    q.push(make_pair(0,1));
    while(q.size())
    {
        int x=q.top().second; q.pop();
        if(v[x]) continue; v[x]=1;
        for(rint i=head[x];i;i=nxt[i])
        {
            int y=ver[i]; if(d[y]<=d[x]+edge[i]) continue;
            d[y]=d[x]+edge[i]; q.push(make_pair(-d[y],y));
        }
    }
}

queue<int> q[N];
il void work(int maxn)
{
    memset(f,0x3f,sizeof(f)); 
    f[1]=0; q[0].push(1);
    for(rint now=0;now<=t;++now) while(q[now].size())
    {
        int x=q[now].front(); q[now].pop(); if(f[x]<now) continue;
        //一个点可能被插入多个队列中
        for(rint i=head[x];i;i=nxt[i])
        {
            int y=ver[i],z=d[x]+edge[i]-d[y];
            if(f[y]<=f[x]+z) continue;
            f[y]=f[x]+z; if(f[y]>maxn) continue;
            q[f[y]].push(y); t=max(t,f[y]);
        }
    }
    For(i,1,n) d[i]=min(d[0],d[i]+f[i]);
}

int main()
{
    n=read(); m=read(); Q=read();
    For(i,1,m) { int x=read(),y=read(),z=read(); add(x,y,z); }
    dij();
    while(Q--)
    {
        int op=read();
        if(op==1)
        {
            int x=read();
            printf("%lld
",d[x]>=d[0]?-1:d[x]);
        }
        else
        {
            int c=read(),k; For(i,1,c) k=read(),++edge[k];
            work(min(c,n-1));
        }
    }
    return 0;
}

以上是关于CF843D-Dynamic-ShortestPath(动态最短路)的主要内容,如果未能解决你的问题,请参考以下文章

cf 843 B Interactive LowerBound [随机化]

cf 843 A Sorting by Subsequences [建图]

843B - Interactive LowerBound

843C - Upgrading Tree

843A - Sorting by Subsequences

843. n-皇后问题