P6348-[PA2011]Journeys【线段树优化建图,最短路】
生活随笔
收集整理的這篇文章主要介紹了
P6348-[PA2011]Journeys【线段树优化建图,最短路】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P6348
題目大意
nnn個點的一張圖,mmm條邊表示區間[a,b][a,b][a,b]向區間[c,d][c,d][c,d]連邊,求單源最短路。
解題思路
線段樹優化建圖的裸題,但是不能直接讓線段樹上的點兩兩建邊,因為這樣是log2nlog^2 nlog2n的顯然空間頂不住。每條邊多建立一個點就好了。
然后最短路可以用雙端隊列bfsbfsbfs但是這里還是寫dijdijdij了,因為雙端隊列bfsbfsbfs寫掛過兩次。
時間復雜度O(nlog?n)O(n\log n)O(nlogn)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define mp(x,y) make_pair(x,y) using namespace std; const int N=4e6+10; struct node{int to,next,w; }a[N<<2]; int n,m,s,num,tot,ls[N]; int q[N],p[N],f[N];bool v[N]; void addl(int x,int y,int w){a[++tot].to=y;a[tot].next=ls[x];a[tot].w=w;ls[x]=tot;return; } void Build(int x,int l,int r){if(l==r){q[x]=p[x]=l;return;}p[x]=++num;q[x]=++num;int mid=(l+r)>>1;Build(x*2,l,mid);Build(x*2+1,mid+1,r);addl(p[x],p[x*2],0);addl(p[x],p[x*2+1],0);addl(q[x*2],q[x],0);addl(q[x*2+1],q[x],0);return; } void Access(int x,int L,int R,int l,int r,int pos){if(L==l&&R==r){if(pos>0)addl(q[x],pos,1);else addl(-pos,p[x],0);return;}int mid=(L+R)>>1;if(r<=mid)Access(x*2,L,mid,l,r,pos);else if(l>mid)Access(x*2+1,mid+1,R,l,r,pos);else Access(x*2,L,mid,l,mid,pos),Access(x*2+1,mid+1,R,mid+1,r,pos);return; } void Dij(){memset(f,0x3f,sizeof(f));priority_queue<pair<int,int> >q;q.push(mp(0,s));f[s]=0;while(!q.empty()){int x=q.top().second;q.pop();if(v[x])continue;v[x]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(f[x]+a[i].w<f[y]){f[y]=f[x]+a[i].w;q.push(mp(-f[y],y));}}}return; } int main() { // printf("%d",sizeof(a)/1024/1024);scanf("%d%d%d",&n,&m,&s);num=n;Build(1,1,n);for(int i=1;i<=m;i++){int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);++num;Access(1,1,n,a,b,num);Access(1,1,n,c,d,-num);++num;Access(1,1,n,c,d,num);Access(1,1,n,a,b,-num);}Dij();for(int i=1;i<=n;i++)printf("%d\n",f[i]);return 0; }總結
以上是生活随笔為你收集整理的P6348-[PA2011]Journeys【线段树优化建图,最短路】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tp路由器怎么桥接设置方法tplink路
- 下一篇: P5355-[Ynoi2017]由乃的玉