您的位置:首页 > 其它

cf 843 D Dynamic Shortest Path [最短路+bfs]

2018-02-20 16:01 357 查看
题面:

传送门

思路:

真·动态最短路

但是因为每次只加1

所以可以每一次修改操作的时候使用距离分层的bfs,在O(n)的时间内解决修改

这里要用到一个小技巧:

把每条边(u,v)的边权表示为dis[u]+w(u,v)-dis[v],这样边权实际上变成了“这条边离作为最短路的一份子还差了多少”

然后在用这个边权的新图里面更新1到每个点的最短路,再用原来的dis加上这个值,就是当前的最短路了

实际上是把绝对数值转化为了“离最优解的距离”,以此解题

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define inf 1e15
#define mp make_pair
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,cnt,first[100010];ll dis[100010];
struct edge{
int to,next,w;
}a[100010];
inline void add(int u,int v,int w){
a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
}
struct node{
int x;node(){x=0;}
node(int xx){x=xx;}
bool operator <(node r) const {
return dis[x]>dis[r.x];
}
};
int delta[100010];
priority_queue<node>qq;
void spfa(){
int i,u,v;
for(i=1;i<=n;i++) dis[i]=inf;
dis[1]=0;qq.push(node(1));
while(!qq.empty()){
u=qq.top().x;qq.pop();
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(dis[v]>dis[u]+(ll)a[i].w){
dis[v]=dis[u]+(ll)a[i].w;
qq.push(node(v));
}
}
}
}
queue<int>q[100010];
void bfs(){
memset(delta,0x3f,sizeof(delta));
int i,j,u,v,w,maxn,head=0,tail=1;
q[0].push(1);delta[1]=maxn=0;
for(i=0;i<=maxn;i++){
while(!q[i].empty()){
u=q[i].front();q[i].pop();
if(i>delta[u]) continue;
for(j=first[u];~j;j=a[j].next){
v=a[j].to;w=a[j].w;
if(delta[v]>delta[u]+dis[u]+w-dis[v]){
delta[v]=delta[u]+dis[u]+w-dis[v];
if(delta[v]<=n){
q[delta[v]].push(v);maxn=max(maxn,delta[v]);
}
}
}
}
}
}
int main(){
//    freopen("d.in","r",stdin);
memset(first,-1,sizeof(first));
int i,j,t1,t2,t3,Q;
n=read();m=read();Q=read();
for(i=1;i<=m;i++){
t1=read();t2=read();t3=read();
add(t1,t2,t3);
}
spfa();
for(i=1;i<=Q;i++){
t1=read();
if(t1==1) t2=read(),printf("%I64d\n",(dis[t2]>=inf)?-1:dis[t2]);
else{
t2=read();
memset(delta,0,sizeof(delta));
for(j=1;j<=t2;j++) t3=read(),a[t3].w++;
bfs();
for(j=1;j<=n;j++) dis[j]+=(ll)delta[j];
//            cout<<endl;
}
}
//    system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: