bzoj 2304 [Apio 2011 path]

来源:互联网 发布:杭州软件app 编辑:程序博客网 时间:2024/05/16 08:13

喜闻乐见的最短路。

关于如何求最短路,dijstra+heap

关于如何构图,详见《APIO2011寻路解题报告》


代码很长,勿喷。。。
感觉map不靠谱,手写点离散化

然后居然冲进第一版了。。。


vfk似乎说过这道题代码超过6k的都是弱菜,所以我是大蒟蒻。


#include<map>#include<stack>#include<queue>#include<ctime>#include<cmath>#include<string>#include<cstdio>#include<cstdlib>#include<cstring>#include<utility>#include<iostream>#include<algorithm>const int MAXN = 1005,Nya = -1, SIZE = 2e9+2,INF = 0x3f3f3f3f, NodeNum = MAXN*12;const long long LINF = 1e14;struct Point{int x,y;Point(){}Point(int x,int y):x(x),y(y){}}ptmp;struct Square{int id,xl,xr,yl,yr;Square(){}Square(int id,int xl,int xr,int yl,int yr):id(id),xl(xl),xr(xr),yl(yl),yr(yr){}};struct SqSide{Point up[2],down[2],left[2],right[2];};struct Edge{int v,next;long long w;Edge(){}Edge(int v,long long w,int next):v(v),w(w),next(next){}};bool cmpl(const Square &a,const Square &b){return a.xl < b.xl;}bool cmpr(const Square &a,const Square &b){return a.xr < b.xr;}bool cmpu(const Square &a,const Square &b){return a.yr < b.yr;}bool cmpd(const Square &a,const Square &b){return a.yl < b.yl;}bool cmpi(const Square &a,const Square &b){return a.id < b.id;}bool cmpx(const Point &a,const Point &b){if(a.x!=b.x)return a.x < b.x;else return a.y < b.y;}bool cmpy(const Point &a,const Point &b){if(a.y!=b.y)return a.y < b.y;else return a.x < b.x;}#define Trans(x,y) ((long long)(x)*SIZE+(y))#define Find(x) (std::lower_bound(nd+1,nd+dl+1,(x))-nd)#define Mp(x,y) std::make_pair(x,y)int n;Point S,T;Square ss[MAXN];SqSide sq[MAXN];int sn[MAXN<<1],sl;long long nd[NodeNum];int dl; int head[NodeNum],el;Edge edge[NodeNum<<2];void NewEdge(int u,int v,long long w){    ++el, edge[el] = Edge(v,w,head[u]), head[u] = el;}long long GetDist(const Point &a,const Point &b){    return (long long)abs(a.x-b.x)+abs(a.y-b.y);}namespace osq{    int head[MAXN], el;    Point v[NodeNum];    int next[NodeNum];      int blen;    Point bowl[NodeNum];    void Clear()    {        el = 0;        memset(head,0,sizeof(head));        memset(next,0,sizeof(next));        memset(v,0,sizeof(v));    }    void Add(int u,const Point &val)    {        ++el, next[el] = head[u], v[el] = val, head[u] = el;    }    void Solve()    {        std::sort(ss+1,ss+n+1,cmpi);        for(int i = 1; i <= n; i++)        {          blen = 0;          for(int j = head[i]; j ; j = next[j])            bowl[++blen] = v[j];              std::sort(bowl+1,bowl+blen+1,cmpx);          for(int k = 1,s1,s2; k < blen; k++)            if(bowl[k].x == bowl[k+1].x)              if(bowl[k].x == ss[i].xl || bowl[k].x == ss[i].xr)                if(bowl[k].y != bowl[k+1].y)                {                    s1 = Find(Trans(bowl[k].x,bowl[k].y));                    s2 = Find(Trans(bowl[k+1].x,bowl[k+1].y));                    long long dist = GetDist(bowl[k],bowl[k+1]);                    NewEdge(s1,s2,dist), NewEdge(s2,s1,dist);                }          std::sort(bowl+1,bowl+blen+1,cmpy);             for(int k = 1,s1,s2; k < blen; k++)            if(bowl[k].y == bowl[k+1].y)             if(bowl[k].y == ss[i].yl || bowl[k].y == ss[i].yr)               if(bowl[k].x != bowl[k+1].x)                {                    s1 = Find(Trans(bowl[k].x,bowl[k].y));                    s2 = Find(Trans(bowl[k+1].x,bowl[k+1].y));                    long long dist = GetDist(bowl[k],bowl[k+1]);                    NewEdge(s1,s2,dist), NewEdge(s2,s1,dist);                }        }    }}int tree[MAXN<<3],nn;namespace seg{    #define L(x) ((x)<<1)    #define R(x) ((x)<<1|1)    void PushDown(int x)    {        if(tree[x] != Nya)        {            tree[L(x)] = tree[R(x)] = tree[x];            tree[x] = Nya;        }    }    int GetColor(int ll,int rr,int k,int si)    {        if(ll == rr) return tree[si];        else        {            int mid = (ll+rr)>>1;            PushDown(si);            if(k <= mid) return GetColor(ll,mid,k,L(si));            else  return GetColor(mid+1,rr,k,R(si));        }    }    void Color(int ll,int rr,int l,int r,int si,int col)    {        if(ll == l && rr == r) tree[si] = col;        else        {            int mid = (ll+rr)>>1;            PushDown(si);            if(r <= mid) Color(ll,mid,l,r,L(si),col);            else if(l > mid) Color(mid+1,rr,l,r,R(si),col);            else             {             Color(ll,mid,l,mid,L(si),col);             Color(mid+1,rr,mid+1,r,R(si),col);            }        }    }}namespace copy{#define Sfind(x) (std::lower_bound(sn+1,sn+nn+1,(x))-sn)#define Gain(P,E,F) sq[ss[i].id].P = ptmp = Point(E,F), osq::Add(ss[tmp].id,ptmp)    void LeftSolve()    {        tree[1] = sl = 0;         std::sort(ss+1,ss+n+1,cmpl);        for(int i = 1; i <= n; i++)          sn[++sl] = ss[i].yl, sn[++sl] = ss[i].yr;        std::sort(sn+1,sn+sl+1);        nn = std::unique(sn+1,sn+sl+1)-(sn+1);        for(int i = 1,s1,s2,tmp; i <= n; i++)        {             s1 = Sfind(ss[i].yl);            tmp = seg::GetColor(1,nn,s1,1);             if(tmp) Gain(left[0],ss[tmp].xr,ss[i].yl);            s2 = Sfind(ss[i].yr);            tmp = seg::GetColor(1,nn,s2,1);            if(tmp) Gain(left[1],ss[tmp].xr,ss[i].yr);             seg::Color(1,nn,s1,s2,1,i);        }      }    void RightSolve()    {        tree[1] = sl = 0;         std::sort(ss+1,ss+n+1,cmpr);        for(int i = 1; i <= n; i++)          sn[++sl] = ss[i].yl, sn[++sl] = ss[i].yr;        std::sort(sn+1,sn+sl+1);        nn = std::unique(sn+1,sn+sl+1)-(sn+1);        for(int i = n,s1,s2,tmp; i >= 1; i--)        {             s1 = Sfind(ss[i].yl);            tmp = seg::GetColor(1,nn,s1,1);             if(tmp) Gain(right[0],ss[tmp].xl,ss[i].yl);            s2 = Sfind(ss[i].yr);            tmp = seg::GetColor(1,nn,s2,1);            if(tmp) Gain(right[1],ss[tmp].xl,ss[i].yr);             seg::Color(1,nn,s1,s2,1,i);        }      }    void UpSolve()    {           tree[1] = sl = 0;         std::sort(ss+1,ss+n+1,cmpu);        for(int i = 1; i <= n; i++)          sn[++sl] = ss[i].xl, sn[++sl] = ss[i].xr;        std::sort(sn+1,sn+sl+1);        nn = std::unique(sn+1,sn+sl+1)-(sn+1);        for(int i = n,s1,s2,tmp; i >= 1; i--)        {             s1 = Sfind(ss[i].xl);            tmp = seg::GetColor(1,nn,s1,1);             if(tmp) Gain(up[0],ss[i].xl,ss[tmp].yl);            s2 = Sfind(ss[i].xr);            tmp = seg::GetColor(1,nn,s2,1);            if(tmp) Gain(up[1] ,ss[i].xr,ss[tmp].yl);            seg::Color(1,nn,s1,s2,1,i);        }    }    void DownSolve()    {        tree[1] = sl = 0;         std::sort(ss+1,ss+n+1,cmpu);        for(int i = 1; i <= n; i++)          sn[++sl] = ss[i].xl, sn[++sl] = ss[i].xr;        std::sort(sn+1,sn+sl+1);        nn = std::unique(sn+1,sn+sl+1)-(sn+1);        for(int i = 1,s1,s2,tmp; i <= n; i++)        {             s1 = Sfind(ss[i].xl);            tmp = seg::GetColor(1,nn,s1,1);             if(tmp) Gain(down[0] ,ss[i].xl,ss[tmp].yr);            s2 = Sfind(ss[i].xr);            tmp = seg::GetColor(1,nn,s2,1);            if(tmp) Gain(down[1] ,ss[i].xr,ss[tmp].yr);            seg::Color(1,nn,s1,s2,1,i);        }    }}#define Insert(g)   if(g[0].x != INF) nd[++dl] = Trans(g[0].x,g[0].y);\                    if(g[1].x != INF) nd[++dl] = Trans(g[1].x,g[1].y);void GetAllNode(){    std::sort(ss+1,ss+n+1,cmpi);    for(int i = 1; i <= n; i++)    {        Insert(sq[i].up);        Insert(sq[i].down);        Insert(sq[i].left);        Insert(sq[i].right);        nd[++dl] = Trans(ss[i].xl,ss[i].yl),        nd[++dl] = Trans(ss[i].xl,ss[i].yr),        nd[++dl] = Trans(ss[i].xr,ss[i].yl),        nd[++dl] = Trans(ss[i].xr,ss[i].yr);    }    std::sort(nd+1,nd+dl+1);    dl = std::unique(nd+1,nd+dl+1)-(nd+1);}#define Connect(g)                                      \        if(g.x != INF)                                  \        {                                               \         s2 = Find(Trans(g.x,g.y));                     \         dist = GetDist(ptmp,g);                        \         NewEdge(s1,s2,dist),NewEdge(s2,s1,dist);       \        }void BuildGraph(){    std::sort(ss+1,ss+n+1,cmpi);    for(int i = 1,s1,s2; i <= n; i++)    {        long long dist;         ptmp = Point(ss[i].xl,ss[i].yr);        s1 = Find(Trans(ss[i].xl,ss[i].yr));        Connect(sq[i].up[0]);        Connect(sq[i].left[1]);        ptmp = Point(ss[i].xr,ss[i].yl);        s1 = Find(Trans(ss[i].xr,ss[i].yl));        Connect(sq[i].down[1]);        Connect(sq[i].right[0]);        ptmp = Point(ss[i].xl,ss[i].yl);        s1 = Find(Trans(ss[i].xl,ss[i].yl));        Connect(sq[i].down[0]);        Connect(sq[i].left[0]);        ptmp = Point(ss[i].xr,ss[i].yr);        s1 = Find(Trans(ss[i].xr,ss[i].yr));        Connect(sq[i].up[1]);        Connect(sq[i].right[1]);    }    for(int i = 1; i <= n; i++)    {        ptmp = Point(ss[i].xl,ss[i].yl),osq::Add(ss[i].id,ptmp);        ptmp = Point(ss[i].xr,ss[i].yl),osq::Add(ss[i].id,ptmp);        ptmp = Point(ss[i].xl,ss[i].yr),osq::Add(ss[i].id,ptmp);        ptmp = Point(ss[i].xr,ss[i].yr),osq::Add(ss[i].id,ptmp);    }    osq::Solve();}typedef std::pair<long long,int> HeapNode;std::priority_queue<HeapNode,std::vector<HeapNode>,std::greater<HeapNode> >  heap;bool flag[NodeNum];#define num secondlong long Dijstra(int s,int t){    static long long dist[NodeNum];    memset(flag,false,sizeof(flag));    for(int i = 1; i <= dl; i++)      dist[i] = LINF;    dist[s] = 0;    heap.push(Mp(0,s));    while(!heap.empty())    {        int x = heap.top().num;        heap.pop();        if(flag[x])continue;        flag[x] = true;        for(int i = head[x]; i ; i = edge[i].next)        {            int p = edge[i].v;long long tmp = dist[x] + edge[i].w;            if(tmp < dist[p]) dist[p] = tmp, heap.push(Mp(dist[p],p));        }    }    return dist[t];}void Solve(){    copy::UpSolve();    copy::DownSolve();    copy::LeftSolve();    copy::RightSolve();    GetAllNode();    BuildGraph();    int st = Find(Trans(S.x,S.y)),ed = Find(Trans(T.x,T.y));    long long ans = Dijstra(st,ed);    if(ans < LINF)      printf("%lld\n",ans);    else       puts("No Path");  }void Clear(){    dl = el = 0;    memset(sq,0x3f3f3f3f,sizeof(sq));    memset(head,0,sizeof(head));    osq::Clear();}void Init(){    scanf("%d%d%d%d",&S.x,&S.y,&T.x,&T.y);    scanf("%d",&n);    for(int i = 1,x1,y1,x2,y2; i <= n; i++)    {      scanf("%d%d%d%d",&x1,&y1,&x2,&y2);      if(x1 > x2) std::swap(x1,x2);      if(y1 > y2) std::swap(y1,y2);      ss[i] = Square(i,x1,x2,y1,y2);    }    ss[n+1] = Square(n+1,S.x,S.x,S.y,S.y);    ss[n+2] = Square(n+2,T.x,T.x,T.y,T.y);    n += 2;}int main(){    int Case;#ifndef ONLINE_JUDGE    freopen("path.in","r",stdin);    freopen("path.out","w",stdout);#endif    scanf("%d",&Case);    while(Case--)    {      Clear();      Init();      Solve();              }#ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif}
0 0
原创粉丝点击