bzoj3073Journeys(線段樹優化最短路)
阿新 • • 發佈:2018-12-22
zoj pac https pre tor fill pair return water
這裏還是一道涉及到區間連邊的問題。
如果暴力去做,那麽就會爆炸
那麽這時候就需要線段樹來優化了。
因為是雙向邊
所以需要兩顆線段樹來分別對應入邊和出邊
QwQ然後做就好了咯
不過需要註意的是,這個邊數的大小不好掌握,以後碰到這種題還是要仔細算一算的
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #define pa pair<int,int> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch==‘-‘) f=-1;ch=getchar();} while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } const int maxn = 5000010; const int maxm = 9e6+1e2; int f[2*maxn],g[2*maxn]; int leaf[maxn]; int point[maxn],nxt[maxm],to[maxm],val[maxm]; int cnt,s,t; int dis[maxn],vis[maxn]; int tmp; int n,m; priority_queue<pa,vector<pa>,greater<pa> > q; void addedge(int x,int y,int w) { nxt[++cnt]=point[x]; to[cnt]=y; val[cnt]=w; point[x]=cnt; } void insert(int x,int y,int w) { addedge(x,y,w); addedge(y,x,w); } void build(int root,int l,int r) { if (l==r) { leaf[l]=++tmp; f[root]=tmp; return; } f[root]=++tmp; int mid = (l+r) >> 1; build(2*root,l,mid); build(2*root+1,mid+1,r); addedge(f[root],f[2*root],0); addedge(f[root],f[2*root+1],0); } void build1(int root,int l,int r) { if (l==r) { g[root]=leaf[l]; return; } g[root]=++tmp; int mid = (l+r) >> 1; build1(2*root,l,mid); build1(2*root+1,mid+1,r); addedge(g[2*root],g[root],0); addedge(g[2*root+1],g[root],0); } void update(int root,int l,int r,int x,int y,int p) { if (x<=l && r<=y) { addedge(p,f[root],1); return; } int mid = (l+r) >> 1; if (x<=mid) update(2*root,l,mid,x,y,p); if (y>mid) update(2*root+1,mid+1,r,x,y,p); } void update1(int root,int l,int r,int x,int y,int p) { if (x<=l && r<=y) { addedge(g[root],p,0); return; } int mid = (l+r) >> 1; if (x<=mid) update1(2*root,l,mid,x,y,p); if (y>mid) update1(2*root+1,mid+1,r,x,y,p); } void dijkstra(int s) { memset(dis,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[leaf[s]]=0; q.push(make_pair(0,leaf[s])); while (!q.empty()) { //cout<<1<<endl; int x=q.top().second; q.pop(); if (vis[x]) continue; vis[x]=1; for (int i=point[x];i;i=nxt[i]) { int p = to[i]; if (dis[p]>dis[x]+val[i]) { dis[p]=dis[x]+val[i]; q.push(make_pair(dis[p],p)); } } } } int main() { n=read(),m=read(),s=read(); build(1,1,n); build1(1,1,n); for (int i=1;i<=m;i++) { int l,r,l1,r1; l=read(),r=read(); l1=read(),r1=read(); int cnt1=++tmp; int cnt2=++tmp; update(1,1,n,l,r,cnt1); update1(1,1,n,l1,r1,cnt1); update(1,1,n,l1,r1,cnt2); update1(1,1,n,l,r,cnt2); } dijkstra(s); for (int i=1;i<=n;i++) { printf("%d",dis[leaf[i]]); if (i!=n) printf("\n"); } return 0; }
bzoj3073Journeys(線段樹優化最短路)