codeforces843D Dynamic Shortest Path -- 最短路

来源:互联网 发布:apache官方下载32位 编辑:程序博客网 时间:2024/06/06 13:20

先对原图求出每个点到 1 的最短路 di,然后对于原权值为 x 的边 (u,v) ,将它的权值改为 du+xdv 。这样,如果 (u,v)1v 的最短路上,它的边权为 0
每次询问时在新图中将对应边权加上后,边权超过 c 的边就不用考虑了。于是可以直接 O(n) 求出新图每个点到 1 的最短路 fi
然后用 fi+di 更新 di 就可以了。
时间复杂度 O(q×n+c)

具体可以看代码。

代码

#include<queue>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define N 100010#define ll long longconst ll INF = 1e15;struct Edge{    int t,nx,w;}e[N<<1];queue<int>g[N];ll d[N],f[N],y;int i,j,k,n,m,q,x,h[N];struct Node{    int x;    Node(int x=0):x(x){}    bool operator < (Node a)const{        return d[x]>d[a.x];    }};priority_queue<Node>Q;inline void Dij(){    for(i=2;i<=n;i++)d[i]=INF;    Q.push(Node(1));    while(!Q.empty()){        x=Q.top().x;Q.pop();        for(int j=h[x];j;j=e[j].nx)        if(d[e[j].t]>d[x]+e[j].w){            d[e[j].t]=d[x]+e[j].w;            Q.push(e[j].t);        }    }}int main(){    scanf("%d%d%d",&n,&m,&q);    for(i=1;i<=m;i++)scanf("%d%d%d",&x,&e[i].t,&e[i].w),e[i].nx=h[x],h[x]=i;    Dij();    while(q--){        scanf("%d%d",&x,&k);        if(x==1)printf("%I64d\n",d[k]>=INF?-1:d[k]);else{            for(i=1;i<=k;i++)scanf("%d",&x),e[x].w++;            for(i=2;i<=n;i++)f[i]=INF;            g[m=0].push(1);if(k>=n)k=n-1;            for(i=0;i<=m;i++){                while(!g[i].empty()){                    x=g[i].front();g[i].pop();                    if(i>f[x])continue;                    for(j=h[x];j;j=e[j].nx){                        y=f[x]+d[x]+e[j].w-d[e[j].t];                        if(f[e[j].t]>y){                            f[e[j].t]=y;                            if(y<=k){                                g[y].push(e[j].t);                                if(y>m)m=y;                            }                        }                    }                }            }            for(i=2;i<=n;i++)d[i]=min(INF,d[i]+f[i]);        }    }    return 0;}
原创粉丝点击