本题因为设计到区间到区间的连边,因此使用线段树优化建图
原理就是用out树和in树,一棵儿子向父亲连边,一棵父亲向儿子连边,然后叶子和叶子连边,对于两个区间的连边,用一个附加节点来表示连接。
建树使用动态开点,但是本题的内存需要计算,不然就会出现开大mle,小则re的尴尬情况
建完图后就是跑一下最短路即可。每个人的线段树优化建图都不相同,挑一个喜欢的模板即可,但是注意,有些模板题是只有点到区间或者区间到点,他们可能没有用附加节点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=1e5+10; const int M=1e5+10; const ll inf=1e18; int cnt; int X[N],Y[N]; struct node{ int l,r; int id; }in[N<<2],out[N<<2]; struct pd{ int id; ll w; bool operator <(const pd &t) const{ return w>t.w; } }; int n,m,p,Q; int id1[18*N+2*M+2],id2[18*N+2*M+2]; vector<pd> g[18*N+2*M+2]; ll dis[18*N+2*M+2]; bool vis[18*N+2*M+2]; priority_queue<pd> q; void add(int u,int v,int w){ g[u].push_back({v,w}); } int build(int k,int l,int r,node tr[],int *a,int type){ tr[k]={l,r,++cnt}; if(l==r){ a[l]=cnt; return tr[k].id; } int mid=l+r>>1; if(type){ add(tr[k].id,build(k<<1,l,mid,tr,a,type),0); add(tr[k].id,build(k<<1|1,mid+1,r,tr,a,type),0); } else{ add(build(k<<1,l,mid,tr,a,type),tr[k].id,0); add(build(k<<1|1,mid+1,r,tr,a,type),tr[k].id,0); } return tr[k].id; } void modify(int u,int l,int r,int now,node tr[],int w,int type){ if(tr[u].l>=l&&tr[u].r<=r){ if(type) add(now,tr[u].id,w); else add(tr[u].id,now,w); return ; } int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,now,tr,w,type); if(r>mid) modify(u<<1|1,l,r,now,tr,w,type); } void dij(){ while(q.size()){ auto t=q.top(); q.pop(); if(vis[t.id]) continue; vis[t.id]=1; for(int i=0;i<(int)g[t.id].size();i++){ int j=g[t.id][i].id; if(dis[j]>dis[t.id]+g[t.id][i].w){ dis[j]=dis[t.id]+g[t.id][i].w; q.push({j,dis[j]}); } } } } int main(){ ios::sync_with_stdio(false); cin>>n>>m>>p>>Q; build(1,1,2*n,in,id1,0); build(1,1,2*n,out,id2,1); int i; for(i=1;i<=2*n;i++){ add(id1[i],id2[i],0); add(id2[i],id1[i],0); } while(m--){ int a,b,c,d,w; cin>>a>>b>>c>>d>>w; c+=n,d+=n; modify(1,a,b,++cnt,in,w,0); modify(1,c,d,cnt,out,0,1); modify(1,c,d,++cnt,in,w,0); modify(1,a,b,cnt,out,0,1); } for(i=1;i<=p;i++) cin>>X[i]; for(i=1;i<=Q;i++){ cin>>Y[i]; Y[i]+=n; } for(i=1;i<=cnt;i++){ dis[i]=1e18; } for(i=1;i<=Q;i++){ dis[id1[Y[i]]]=0; q.push({id1[Y[i]],0}); } dij(); ll ans=0; for(i=1;i<=p;i++){ ans=max(ans,dis[id2[X[i]]]); } if(ans==inf){ cout<<"boring game"<<endl; } else{ cout<<ans<<endl; } }