ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【BZOJ3073】[PA2011] Journeys(线段树优化建图模板)

2020-06-01 18:56:25  阅读:240  来源: 互联网

标签:连边 FS BZOJ3073 Journeys int PA2011 边线 节点 define


点此看题面

大致题意: 有\(n\)个点,每次在区间\([a,b]\)和区间\([c,d]\)之间连一条无向边,求从起点出发到所有点的最短路。

线段树优化建图模板

一道板子题。

考虑建两棵线段树,一棵表示出边,一棵表示入边。

初始化建树时,出边线段树上每个子节点向父节点连边,入边线段树上每个父节点向子节点连边。

然后对于一次连边操作,我们把无向边拆成两条有向边,从一个区间向另一个区间连边。

则我们可以新建一个虚拟节点,在出边线段树上区间向该节点连边,然后由该节点向入边线段树上的区间连边。

注意这两条边中只需一条权值设为\(1\),不然答案会翻倍。

最后还要记得从出边线段树上每个叶节点向入边线段树上自身的对应节点连边。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 500000
#define M 100000
#define DT 5000000
#define ET 10000000
#define add(x,y,v) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=v)
using namespace std;
int n,m,s,tot,ee,lnk[DT+5];struct edge {int to,nxt,val;}e[2*ET+5];
class FastIO
{
	private:
		#define FS 100000
		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
		#define pc(c) (C==E&&(clear(),0),*C++=c)
		#define D isdigit(c=tc())
		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
	public:
		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
		Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
		Tp I void writeln(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc('\n');} 
		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
		#undef D
}F;
template<int op> class SegmentTree//线段树优化建图,op=0为出边线段树,op=1为入边线段树
{
	private:
		#define PT CI l=1,CI r=n,CI rt=1
		#define LT l,mid,rt<<1
		#define RT mid+1,r,rt<<1|1
		int P[N<<2];
	public:
		I void Build(PT)//建树
		{
			if(l==r) return (void)(P[rt]=(op^(l==s))?l:n+l);int mid=l+r>>1;P[rt]=++tot,
			Build(LT),op?add(P[rt],P[rt<<1],0):add(P[rt<<1],P[rt],0),
			Build(RT),op?add(P[rt],P[rt<<1|1],0):add(P[rt<<1|1],P[rt],0);
		}
		I void Add(CI L,CI R,CI t,PT)//连边
		{
			if(L<=l&&r<=R) return (void)(op?add(t,P[rt],op):add(P[rt],t,op));int mid=l+r>>1;
			L<=mid&&(Add(L,R,t,LT),0),R>mid&&(Add(L,R,t,RT),0);
		}
};SegmentTree<0> SO;SegmentTree<1> SI;
class Dijkstra//最短路
{
	private:
		#define mp make_pair
		#define fir first
		#define sec second
		int dis[DT+5],vis[DT+5];typedef pair<int,int> Pr;
		priority_queue<Pr,vector<Pr>,greater<Pr> > q;
	public:
		I int operator [] (CI x) Con {return dis[x];}
		I void Dij(CI s)
		{
			RI i;Pr k;for(i=1;i<=tot;++i) dis[i]=1e9;q.push(mp(dis[s]=0,s));//初始化
			W(!q.empty())
			{
				if(k=q.top(),q.pop(),vis[k.sec]) continue;vis[k.sec]=1;
				for(i=lnk[k.sec];i;i=e[i].nxt) k.fir+e[i].val<dis[e[i].to]&&
					(q.push(mp(dis[e[i].to]=k.fir+e[i].val,e[i].to)),0);
			}
		}
}D;
int main()

	RI i,a,b,c,d;F.read(n,m,s),tot=2*n,SO.Build(),SI.Build();//初始化
	for(i=1;i<=n;++i) i^s&&add(i,n+i,0);//从出边线段树向入边线段树对应点连边
	for(i=1;i<=m;++i) F.read(a,b,c,d),
		++tot,SO.Add(a,b,tot),SI.Add(c,d,tot),//把无向边拆成两条有向边
		++tot,SO.Add(c,d,tot),SI.Add(a,b,tot);
	for(D.Dij(s),i=1;i<=n;++i) F.writeln(D[i]);return F.clear(),0;
}

标签:连边,FS,BZOJ3073,Journeys,int,PA2011,边线,节点,define
来源: https://www.cnblogs.com/chenxiaoran666/p/BZOJ3073.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有