最短路-HZNUoj-2798 (使用线段树来进行区间压缩)

题目传送门

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) (1n105,1m5×104)

接下来 m 行,每行三个正整数 u , v , w u,v,w u,v,w,表示存在一条 uv 距离为 w 的单向路径。
( 1 ≤ u , v ≤ n , 1 ≤ w ≤ 1 0 9 ) (1≤u,v≤n,1≤w≤10^9) (1u,vn,1w109)

然后一行一个正整数 q ,表示 ZC 搭建的道路数。 ( 1 ≤ q ≤ 5 × 1 0 4 ) (1≤q≤5×10^4) (1q5×104)

接下来 q 行,每行五个正整数,对应上文中 ZC 搭建道路的方式。 ( 1 ≤ u , L , R ≤ n , 1 ≤ w ≤ 1 0 9 ) (1≤u,L,R≤n,1≤w≤10^9) (1u,L,Rn,1w109)

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 自己)

扫描二维码关注公众号,回复: 12817221 查看本文章

如果 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 disu>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;
}

猜你喜欢

转载自blog.csdn.net/bloom_er/article/details/107912487
今日推荐