题目链接:https://codeforces.com/contest/787/problem/D
题目大意:有n个星球,你有q个单向传送门
类型1,$u$ $v$ $w$,表示从$u$到$v$花费$w$
类型2,$u$ $l$ $r$ $w$,表示从$u$到区间$[l,r]$中的任意的星球,花费$w$
类型3,$u$ $l$ $r$ $w$,表示从$[l,r]$中任意的星球到$u$,花费$w$,
问从s开始到每个星球的最短距离,如果无法到达则输出-1
Examples
Input
3 5 1
2 3 2 3 17
2 3 2 2 16
2 2 2 3 3
3 3 1 1 12
1 3 3 17
Output
0 28 12
Input
4 3 1
3 4 1 3 12
2 2 3 4 10
1 2 4 16
Output
0 -1 -1 12
emmm,之前已经写过了一篇了,现在在做又WA了好几发QAQ。。。以下是以前写的博客,里面有详细的解说
https://blog.csdn.net/qq_43906000/article/details/102256830
主要就是用两颗线段树来对区间建立路径做个优化
贴一下代码吧QAQ
以下是AC代码:
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define lc rt<<1 #define rc rt<<1|1 typedef long long ll; const int mac=1e5+10; const ll inf=1e18+10; struct node { int id; ll s; bool operator<(const node &a)const { return s>a.s; } }; struct Edge { int to,next,w; }eg[mac*20]; ll dis[mac*10]; int head[mac*10],tree1[mac<<2],tree2[mac<<2]; int idx,pa[mac],pb[mac],num; bool vis[mac*10]; void add(int u,int v,int w) { eg[num]=Edge{v,head[u],w}; head[u]=num++; } void build1(int l,int r,int rt) { tree1[rt]=++idx; if (l==r){ pa[l]=tree1[rt]; return; } int mid=(l+r)>>1; build1(lson);build1(rson); add(tree1[rt],tree1[lc],0); add(tree1[rt],tree1[rc],0); } void build2(int l,int r,int rt) { tree2[rt]=++idx; if (l==r){ pb[l]=tree2[rt]; add(pa[l],tree2[rt],0); return; } int mid=(l+r)>>1; build2(lson);build2(rson); add(tree2[lc],tree2[rt],0); add(tree2[rc],tree2[rt],0); } void update_to_range(int l,int r,int rt,int st,int L,int R,int w) { if (l>=L && r<=R){ add(pb[st],tree1[rt],w); return; } int mid=(l+r)>>1; if (mid>=L) update_to_range(lson,st,L,R,w); if (mid<R) update_to_range(rson,st,L,R,w); } void update_to_pos(int l,int r,int rt,int L,int R,int ed,int w) { if (l>=L && r<=R){ add(tree2[rt],pa[ed],w); return; } int mid=(l+r)>>1; if (mid>=L) update_to_pos(lson,L,R,ed,w); if (mid<R) update_to_pos(rson,L,R,ed,w); } void dij(int st) { priority_queue<node>q; q.push(node{st,0}); dis[st]=0; while (!q.empty()){ node now=q.top(); q.pop(); int u=now.id; if (vis[u]) continue; vis[u]=true; for (int i=head[u]; i!=-1; i=eg[i].next){ int v=eg[i].to; if (vis[v]) continue; if (dis[v]>dis[u]+1LL*eg[i].w){ dis[v]=dis[u]+1LL*eg[i].w; q.push(node{v,dis[v]}); } } } } int main(int argc, char const *argv[]) { //freopen("in.txt","r",stdin); int n,q,s; scanf ("%d%d%d",&n,&q,&s); memset(head,-1,sizeof head); build1(1,n,1); build2(1,n,1); for (int i=1; i<=q; i++){ int id,u,v,w,l,r; scanf ("%d",&id); if (id==1) { scanf ("%d%d%d",&u,&v,&w); add(pb[u],pa[v],w); } else{ scanf ("%d%d%d%d",&v,&l,&r,&w); if (id==2) update_to_range(1,n,1,v,l,r,w); else update_to_pos(1,n,1,l,r,v,w); } } for (int i=1; i<n*10; i++) dis[i]=inf; dij(pb[s]); for (int i=1; i<=n; i++){ if (dis[pb[i]]==inf) printf("%d%c",-1,i==n?' ':' '); else printf("%lld%c",dis[pb[i]],i==n?' ':' '); } return 0; }