• CF843D Dynamic Shortest Path


    题意:给你一张有向图。Q:询问1到x点的最短路。C:钦定l条边x1,x2,...,xl的权值+1。

    n<=2e5。

    标程:

     1 #include<bits/stdc++.h>
     2 #define P pair<ll,int>
     3 using namespace std;
     4 int read()
     5 {
     6    int x=0,f=1;char ch=getchar();
     7    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
     8    while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
     9    return x*f;
    10 }
    11 const int N=200005;
    12 typedef long long ll;
    13 const ll inf=1ll<<60;
    14 priority_queue<P,vector<P>,greater<P> >Q;
    15 struct node{int to,next;}num[N];
    16 struct _node{int u,v,w;}e[N];
    17 int cnt,head[N],n,m,qq,vis[N],len,u,v,tmp;
    18 ll dis[N],d[N],x;
    19 queue<int> q[N];
    20 void add(int x,int i) {num[++cnt].next=head[x];num[cnt].to=i;head[x]=cnt;}
    21 void dij()
    22 {
    23     for (int i=2;i<=n;i++) dis[i]=inf;
    24     Q.push(P(0,1));
    25     while (!Q.empty())
    26     {
    27         int u=Q.top().second;Q.pop();
    28         if (vis[u]) continue;vis[u]=1;
    29         for (int i=head[u],v;i;i=num[i].next)
    30           if (v=num[i].to,dis[u]+e[v].w<dis[e[v].v])
    31             dis[e[v].v]=dis[u]+e[v].w,Q.push(P(dis[e[v].v],e[v].v));
    32     }
    33 }
    34 int main()
    35 {
    36     n=read();m=read();qq=read();
    37     for (int i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].w=read(),add(e[i].u,i);
    38     dij();
    39     while (qq--)
    40     {
    41         if (read()==1) x=dis[read()],printf("%lld
    ",x==inf?-1:x);
    42         else {
    43             int k=read();
    44             for (int i=1;i<=k;i++) e[read()].w++;
    45             for (int i=2;i<=n;i++) d[i]=inf;
    46             q[len=0].push(1);k=min(k,n-1);
    47             for (int i=0;i<=len;i++)
    48             {
    49                 while (!q[i].empty())
    50                 {
    51                     u=q[i].front();q[i].pop();
    52                     if (i>d[u]) continue;
    53                     for (int i=head[u];i;i=num[i].next)
    54                       if (v=num[i].to,tmp=d[u]+dis[u]+e[v].w-dis[e[v].v],tmp<d[e[v].v]&&tmp<=k)
    55                             d[e[v].v]=tmp,q[tmp].push(e[v].v),len=max(len,tmp);
    56                 }
    57             }
    58             for (int i=1;i<=n;i++) dis[i]=min(dis[i]+d[i],inf);
    59         }
    60     }
    61    return 0;
    62 }

    题解:dijkstra 差分 桶优化

    noip2017D1T3的思路:给每一条边赋权dis[x]+w(x,y)-dis[y]。如果(x,y)在1到y的最短路上,那么新权=0。某一条路走到x的新权和表示该路的距离与到x最短路的差值。以此来减小最短路的长度,方便表示。

    这里也一样,由于最短路更新时不降,就可以用桶/队列/vector[i]保存最短路为i的点集。从小到大枚举最短路x,并取出x桶中的点来更新其他点。

    k也不小啊,空间开不下?最短路被更新的长度不会多于n-1,所以只用保存n-1的最短路即可。

    时间复杂度O((n+m)logn+q(n+m))。

  • 相关阅读:
    省选模拟17 题解
    省选模拟16 题解
    省选模拟15 题解
    省选模拟14 题解
    省选模拟13 题解
    省选模拟12 题解
    图论专项测试
    数学专题测试4
    省选模拟11 题解
    爬虫框架:scrapy
  • 原文地址:https://www.cnblogs.com/Scx117/p/9112959.html
Copyright © 2020-2023  润新知