题面:
思路:
真·动态最短路
但是因为每次只加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\n",(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 }
来源:oschina
链接:https://my.oschina.net/u/4399904/blog/4237893