bzoj 2304 [Apio 2011 path] 分类: bzoj apio 2015-05-01 20:14 46人阅读 评论(0) 收藏
喜闻乐见的最短路。
关于如何求最短路,
关于如何构图,详见《
代码很长,勿喷。。。
感觉
然后居然冲进第一版了。。。
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 second
long 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
}
版权声明:本文为博主原创文章,未经博主允许不得转载。