题面:
思路:
真·动态最短路
但是因为每次只加1
所以可以每一次修改操作的时候使用距离分层的bfs,在O(n)的时间内解决修改
这里要用到一个小技巧:
把每条边(u,v)的边权表示为dis[u]+w(u,v)-dis[v],这样边权实际上变成了“这条边离作为最短路的一份子还差了多少”
然后在用这个边权的新图里面更新1到每个点的最短路,再用原来的dis加上这个值,就是当前的最短路了
实际上是把绝对数值转化为了“离最优解的距离”,以此解题
Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define ll long long 7 #define inf 1e15 8 #define mp make_pair 9 using namespace std; 10 inline int read(){ 11 int re=0,flag=1;char ch=getchar(); 12 while(ch>'9'||ch<'0'){ 13 if(ch=='-') flag=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); 17 return re*flag; 18 } 19 int n,m,cnt,first[100010];ll dis[100010]; 20 struct edge{ 21 int to,next,w; 22 }a[100010]; 23 inline void add(int u,int v,int w){ 24 a[++cnt]=(edge){v,first[u],w};first[u]=cnt; 25 } 26 struct node{ 27 int x;node(){x=0;} 28 node(int xx){x=xx;} 29 bool operator <(node r) const { 30 return dis[x]>dis[r.x]; 31 } 32 }; 33 int delta[100010]; 34 priority_queue<node>qq; 35 void spfa(){ 36 int i,u,v; 37 for(i=1;i<=n;i++) dis[i]=inf; 38 dis[1]=0;qq.push(node(1)); 39 while(!qq.empty()){ 40 u=qq.top().x;qq.pop(); 41 for(i=first[u];~i;i=a[i].next){ 42 v=a[i].to; 43 if(dis[v]>dis[u]+(ll)a[i].w){ 44 dis[v]=dis[u]+(ll)a[i].w; 45 qq.push(node(v)); 46 } 47 } 48 } 49 } 50 queue<int>q[100010]; 51 void bfs(){ 52 memset(delta,0x3f,sizeof(delta)); 53 int i,j,u,v,w,maxn,head=0,tail=1; 54 q[0].push(1);delta[1]=maxn=0; 55 for(i=0;i<=maxn;i++){ 56 while(!q[i].empty()){ 57 u=q[i].front();q[i].pop(); 58 if(i>delta[u]) continue; 59 for(j=first[u];~j;j=a[j].next){ 60 v=a[j].to;w=a[j].w; 61 if(delta[v]>delta[u]+dis[u]+w-dis[v]){ 62 delta[v]=delta[u]+dis[u]+w-dis[v]; 63 if(delta[v]<=n){ 64 q[delta[v]].push(v);maxn=max(maxn,delta[v]); 65 } 66 } 67 } 68 } 69 } 70 } 71 int main(){ 72 // freopen("d.in","r",stdin); 73 memset(first,-1,sizeof(first)); 74 int i,j,t1,t2,t3,Q; 75 n=read();m=read();Q=read(); 76 for(i=1;i<=m;i++){ 77 t1=read();t2=read();t3=read(); 78 add(t1,t2,t3); 79 } 80 spfa(); 81 for(i=1;i<=Q;i++){ 82 t1=read(); 83 if(t1==1) t2=read(),printf("%I64d ",(dis[t2]>=inf)?-1:dis[t2]); 84 else{ 85 t2=read(); 86 memset(delta,0,sizeof(delta)); 87 for(j=1;j<=t2;j++) t3=read(),a[t3].w++; 88 bfs(); 89 for(j=1;j<=n;j++) dis[j]+=(ll)delta[j]; 90 // cout<<endl; 91 } 92 } 93 // system("pause"); 94 return 0; 95 }