bzoj 2834: 回家的路

题目

F.A.QsHomeDiscussProblemSetStatusRanklistContest入门OJModifyUser   DCOILogout捐赠本站
Notice:1:注册本OJ方式请见https://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=5671 2:替用户ir1d发布如下信息,希望大家能够积极支持。 OI Wiki 致力于成为一个开放自由的 OI 知识整合站点,欢迎感兴趣的同学参与贡献 https://oi-wiki.org

2834: 回家的路

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 183  Solved: 98
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

2 1
1 2
1 1 2 2

Sample Output

5

HINT

 

N<=20000,M<=100000

 

Source

 
[Submit][Status][Discuss]


HOME Back


解法

分层图最短路,将横向与纵向分开即可。

但是只能存下可转移的点与起点和终点。

数据好像有点水,起点和终点好像一定可以换乘

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>
#include <vector>
#include <queue>
#define INF 2139062143
#define MAX 0x7ffffffffffffff
#define del(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
    x=0;T k=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
}
const int maxn=100000+15;
int n,m,s,t,ecnt[2];
struct Q{
    int x,y,id;
}a[maxn];

struct Edge {
    int u,v,w;
    Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w) {}
};
vector<Edge> edge[2];
vector<int> G[maxn][2];
inline void add_edge(int u,int v,int w,int id) {
    edge[id].push_back(Edge(u,v,w));
    edge[id].push_back(Edge(v,u,w));
    ecnt[id]+=2;
    G[u][id].push_back(ecnt[id]-2);
    G[v][id].push_back(ecnt[id]-1);
}

priority_queue< pair<pair<int,int>,int> > q;
int dis[maxn][2];
bool vis[maxn][2];

inline void dij() {
    del(dis,127);dis[s][0]=dis[s][1]=0;
    q.push(make_pair(make_pair(0,s),0));
    q.push(make_pair(make_pair(0,s),1));
    while(!q.empty()) {
        pair<pair<int,int>,int> Node=q.top();q.pop();
        pair<int,int> node=Node.first;
        int id=Node.second,u=node.second,d=-node.first;
        if(vis[u][id]) continue;
        vis[u][id]=1;
        for(int i=0;i<G[u][id].size();i++) {
            Edge& e=edge[id][G[u][id][i]];
            int v=e.v;
            if(dis[v][id]>d+e.w) {
                dis[v][id]=d+e.w;
                q.push(make_pair(make_pair(-dis[v][id],v),id));
            }
            if(dis[v][id^1]>d+e.w+1) {
                dis[v][id^1]=d+e.w+1;
                q.push(make_pair(make_pair(-dis[v][id^1],v),id^1));
            }
        }
    }
    printf("%d\n",(min(dis[m+2][0],dis[m+2][1])==INF)?-1:min(dis[m+2][0],dis[m+2][1]));
}

bool cmp1(Q a,Q b) {
    return (a.x^b.x)?a.x<b.x:a.y<b.y;
}

bool cmp2(Q a,Q b) {
    return (a.y^b.y)?a.y<b.y:a.x<b.x;
}

bool cmp3(Q a,Q b) {
    return a.id<b.id;
}

int main()
{
    read(n),read(m);
    for(int i=1;i<=m;i++) {read(a[i].x),read(a[i].y);a[i].id=i;}
    read(a[m+1].x),read(a[m+1].y);read(a[m+2].x),read(a[m+2].y);a[m+1].id=m+1;a[m+2].id=m+2;
    sort(a+1,a+1+m+2,cmp1);
    for(int i=1;i<m+2;i++) if(a[i].x==a[i+1].x) add_edge(a[i].id,a[i+1].id,2*(a[i+1].y-a[i].y),1);
    sort(a+1,a+1+m+2,cmp2);
    for(int i=1;i<m+2;i++) if(a[i].y==a[i+1].y) add_edge(a[i].id,a[i+1].id,2*(a[i+1].x-a[i].x),0);
    s=m+1;
    dij();
    return 0;
}
View Code
posted @ 2018-10-25 22:06  Mr_asd  阅读(178)  评论(0编辑  收藏  举报