题意:给你一张有向图。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))。