Description
ZC 家所在的小区住着很多学妹,为了方便和学妹们联络感情,ZC 大佬决定在原有的道路上,再建一些道路。由于ZC 太强了,它可以搭建以下两种道路:
1 1 1 u u u L L L R R R w w w:对于区间 L , R L,R L,R 中的每一个位置 i i i,搭建一条 u − > i u -> i u−>i 的长度为 w w w 道路。
2 2 2 L L L R R R u u u w w w:对于区间 L , R L,R L,R 中的每一个位置 i i i,搭建一条 i − > u i -> u i−>u 的长度为 w w w 道路。
已知 ZC 的家在 1 号位置,请问搭建道路后,ZC 到每个学妹家的最短距离是多少?
Input
第一行包含两个正整数 n , m,分别表示位置总数和原有的道路数。
(
1
≤
n
≤
1
0
5
,
1
≤
m
≤
5
×
1
0
4
)
(1≤n≤10^5,1≤m≤5×10^4)
(1≤n≤105,1≤m≤5×104)
接下来 m 行,每行三个正整数
u
,
v
,
w
u,v,w
u,v,w,表示存在一条 u 到 v 距离为 w 的单向路径。
(
1
≤
u
,
v
≤
n
,
1
≤
w
≤
1
0
9
)
(1≤u,v≤n,1≤w≤10^9)
(1≤u,v≤n,1≤w≤109)
然后一行一个正整数 q ,表示 ZC 搭建的道路数。 ( 1 ≤ q ≤ 5 × 1 0 4 ) (1≤q≤5×10^4) (1≤q≤5×104)
接下来 q 行,每行五个正整数,对应上文中 ZC 搭建道路的方式。 ( 1 ≤ u , L , R ≤ n , 1 ≤ w ≤ 1 0 9 ) (1≤u,L,R≤n,1≤w≤10^9) (1≤u,L,R≤n,1≤w≤109)
1
1
1
u
u
u
L
L
L
R
R
R
w
w
w
2
2
2
L
L
L
R
R
R
u
u
u
w
w
w
Output
输出 n 行,每行一个正整数,表示 ZC 到学妹 i 的距离。(包括 ZC 自己)
如果 ZC 无法到达,则输出 −1 。
Samples
input |
---|
5 4 |
1 2 5 |
1 4 10 |
2 3 1 |
3 4 2 |
1 |
1 1 3 5 7 |
output |
---|
0 |
5 |
6 |
7 |
7 |
思路:
求1号点到其余 n-1个点的最短路径
这题有点类似于建层图
对于这道层图题,把层的点设置为
[
n
+
1
,
n
×
2
]
[n+1,n×2]
[n+1,n×2],然后令层点到该层所在节点的距离
d
i
s
(
u
−
>
v
)
=
0
dis(u -> v) =0
dis(u−>v)=0,其余按照正常的建边即可。
同样,本题的思路大体也是进行层图建边。做法参考了zkl学姐的代码
首先令原本
[
1
,
n
]
[1,n]
[1,n]这些点的下标为
1
1
1~
n
n
n,然后令
[
L
,
R
]
[L,R]
[L,R]的区域设置下标点为
[
n
+
1
,
.
.
.
]
[n+1, ...]
[n+1,...]
-
对于optional =1操作,为点到区间,建立第一颗线段树,将对应的区间所在下标 i d x idx idx 存起来,并且令
∀ v ∈ [ L , R ] \forall v\in[L,R] ∀v∈[L,R], 对 i d x − > v idx->v idx−>v建立权值为 0 0 0的边 -
对于optional=2操作,为区间到点的,建立第二颗线段树,同样将下标 i d x idx idx存起来,并且令
∀ v ∈ [ L , R ] \forall v\in[L,R] ∀v∈[L,R],对 v − > i d x v->idx v−>idx建边,权值为 0 0 0 -
对后面查询更改操作,将线段树遍历到 q l < = l , r < = q r ql<=l,r<=qr ql<=l,r<=qr后,将对应的下标 i d x idx idx和 u u u建立权值为 w w w的边即可
-
最后跑一遍 d i j k s t r a dijkstra dijkstra即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename T>
inline void read(T &x)
{
int tmp = 1;char c = getchar();x = 0;
while (c > '9' || c < '0'){if (c == '-')tmp = -1;c = getchar();}
while (c >= '0' && c <= '9'){x = x * 10 + c - '0';c = getchar();}
x *= tmp;
}
const int N=1e5+10;
const int NN=1e6+10;
const int M=1e7+10;
const ll inf=1e14+10;
int head[NN],cnt;
struct edge{
int next,to;
ll w;
edge(){}
edge(int next,int to,ll w):next(next),to(to),w(w){}
}e[M];
void add(int u,int v,ll w){
e[cnt]=edge(head[u],v,w);
head[u]=cnt++;
}
struct Tree{
int l,r,num;
}tree[N<<2][2];
int n,m,tot;
int idx[N<<2][2];
void build(int l,int r,int rt,int op){
tree[rt][op].l=l;
tree[rt][op].r=r;
idx[rt][op]=++tot;
if(op){
for(int i=l;i<=r;++i){
add(tot,i,0);
}
}
else{
for(int i=l;i<=r;++i){
add(i,tot,0);
}
}
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,rt<<1,op);
build(mid+1,r,rt<<1|1,op);
}
int u;
void update(int ql,int qr,ll c,int rt,int op){
if(ql<=tree[rt][op].l&&tree[rt][op].r<=qr){
if(op) add(u,idx[rt][op],c);
else add(idx[rt][op],u,c);
return;
}
int mid=(tree[rt][op].l+tree[rt][op].r)>>1;
if(ql<=mid) update(ql,qr,c,rt<<1,op);
if(mid<qr) update(ql,qr,c,rt<<1|1,op);
}
ll dis[NN];
struct node{
int v;ll w;
node(int v,ll w):v(v),w(w){}
bool friend operator <(const node &a,const node &b){
return a.w>b.w;
}
};
bool vis[NN];
void dijkstra(){
priority_queue<node>que;
for(int i=1;i<=tot;++i) dis[i]=inf;
memset(vis,false,sizeof vis);
dis[1]=0;
que.push(node(1,0));
while(!que.empty()){
node vn=que.top();
que.pop();
if(vis[vn.v]) continue;
int u=vn.v;
vis[u]=1;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(vis[v]) continue;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
que.push(node(v,dis[v]));
}
}
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(nullptr); cout.tie(nullptr);
read(n);read(m);
memset(head,-1,sizeof head);cnt=0;
while(m--){
int u,v,w;read(u);read(v);read(w);
add(u,v,w);
}
tot=n;
build(1,n,1,1);
build(1,n,1,0);
int T;read(T);
while(T--){
int op;read(op);
if(op&1){
int l,r;ll w;
read(u),read(l),read(r),read(w);
update(l,r,w,1,1);
}
else{
int l,r;ll w;
read(l);read(r);read(u);read(w);
update(l,r,w,1,0);
}
}
dijkstra();
for(int i=1;i<=n;++i){
if(dis[i]==inf) puts("-1");
else printf("%lld\n",dis[i]);
}
return 0;
}