BZOJ 2834 回家的路

Posted on 2016-09-20 12:59  ziliuziliu  阅读(136)  评论(0编辑  收藏  举报

分层图最短路。边要开够。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxv 300500
#define maxe 2000500
#define inf 2147483647
using namespace std;
struct pnt
{
    int x,y,id;
}p[maxv];
struct edge
{
    int v,w,nxt;
}e[maxe];
int n,m,x,y,cnt=0,dis[maxv],nume=0,g[maxv],ans=inf;
bool vis[maxv];
queue <int> q;
void addpnt(int x,int y){cnt++;p[cnt].x=x;p[cnt].y=y;p[cnt].id=cnt;}
bool cmp1(pnt x,pnt y){if (x.x==y.x) return x.y<y.y;return x.x<y.x;}
bool cmp2(pnt x,pnt y){if (x.y==y.y) return x.x<y.x;return x.y<y.y;}
void addedge(int u,int v,int w)
{
    e[++nume].v=v;
    e[nume].w=w;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void spfa(int x)
{
    while (!q.empty()) q.pop();
    for (int i=1;i<=2*cnt;i++) vis[i]=false,dis[i]=inf;
    vis[x]=true;q.push(x);dis[x]=0;
    while (!q.empty())
    {
        int head=q.front();q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (dis[v]>dis[head]+e[i].w)
            {
                dis[v]=dis[head]+e[i].w;
                if (!vis[v]) {vis[v]=true;q.push(v);}
            }
        }
        vis[head]=false;
    }
}
int main()
{
    scanf("%d%d",&m,&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        addpnt(x,y);
    }
    scanf("%d%d",&x,&y);addpnt(x,y);
    scanf("%d%d",&x,&y);addpnt(x,y);
    sort(p+1,p+cnt+1,cmp1);
    for (int i=1;i<=cnt-1;i++)
    {
        if (p[i].x==p[i+1].x)
        {
            addedge(p[i].id,p[i+1].id,(p[i+1].y-p[i].y)<<1);
            addedge(p[i+1].id,p[i].id,(p[i+1].y-p[i].y)<<1);
        }
    }
    sort(p+1,p+cnt+1,cmp2);
    for (int i=1;i<=cnt-1;i++)
    {
        if (p[i].y==p[i+1].y)
        {
            addedge(p[i].id+cnt,p[i+1].id+cnt,(p[i+1].x-p[i].x)<<1);
            addedge(p[i+1].id+cnt,p[i].id+cnt,(p[i+1].x-p[i].x)<<1);
        }
    }
    for (int i=1;i<=n;i++)
    {
        addedge(i,i+cnt,1);
        addedge(i+cnt,i,1);
    }
    spfa(n+1);ans=min(ans,dis[n+2]);ans=min(ans,dis[n+2+cnt]);
    spfa(n+1+cnt);ans=min(ans,dis[n+2]);ans=min(ans,dis[n+2+cnt]);
    if (ans==inf) printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}