1. 程式人生 > >bzoj3073Journeys(線段樹優化最短路)

bzoj3073Journeys(線段樹優化最短路)

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(線段樹優化最短路)