先对原图求出每个点到
1
的最短路
每次询问时在新图中将对应边权加上后,边权超过
然后用
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 long
const 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;
}