羅区P3831 [SHOI2012]帰り道
トピック:
ソリューション:
- 階層グラフ。
- 階層グラフの非常に良い、さらなる理解。
- 図層化は、すべての図が示されている状態である、と異なる状態間で互いに干渉する。これは、問題がある場合、階層グラフメソッドが第二の方法を使用することで作ることができない、両方の方法障害状況を取るようには見えない、解決する方法または第二の方法によって解決することができることを意味します。
- 質問のこの問題の意味:トレリス、彼らは最低限の二つの点で尋ねられたとき、彼らは、1の上になっていた場合には、特定の時点でのみ回し、2とするとき、エッジを行っていた場合。
- 唯一のポイントは、順方向マークを来ているので、それは、エンドポイントに最初から届く(開始および終了マーカーも考慮されている)するために標識されている必要があります。そして、それが私たちの配慮の範囲をマーク点の間だけの関係です。
- マークされた点について、回転方向です。
- 唯一の水平方向と垂直方向があるので、この質問は、投入された決定は、私たちはそれぞれ、これらの二つの方向のいずれかを確立しました。すなわち、一つだけの画像も横方向縁部、1つでも長手方向縁部。
- その後、垂直に離れて水平方向から示す第1の層及び第二層であっても1つの側の重量、同じ点はダウン1はコストがかかります。
- 最後に、あなたは最短パスを実行することができます。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 1000005
#define M 1000005
using namespace std;
struct Node
{
int val, pos;
friend bool operator < (Node x, Node y) {
return x.val > y.val;
}
};
struct E {int next, to, dis;} e[M];
struct A {int x, y, id;} a[N];
int n, m, num;
int h[N], dis[N];
bool vis[N];
int read()
{
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x;
}
bool cmp1(A u, A v)
{
if(u.x == v.x) return u.y < v.y;
return u.x < v.x;
}
bool cmp2(A u, A v)
{
if(u.y == v.y) return u.x < v.x;
return u.y < v.y;
}
void add(int u, int v, int w)
{
e[++num].next = h[u];
e[num].to = v;
e[num].dis = w;
h[u] = num;
}
int main()
{
cin >> n >> m;
n = m + 2;
for(int i = 1; i <= n; i++)
{
a[i].x = read();
a[i].y = read();
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp1);
for(int i = 2; i <= n; i++)
if(a[i - 1].x == a[i].x)
{
add(a[i - 1].id, a[i].id, (a[i].y - a[i - 1].y) * 2);
add(a[i].id, a[i - 1].id, (a[i].y - a[i - 1].y) * 2);
}
sort(a + 1, a + 1 + n, cmp2);
for(int i = 2; i <= n; i++)
if(a[i - 1].y == a[i].y)
{
add(a[i - 1].id + n, a[i].id + n, (a[i].x - a[i - 1].x) * 2);
add(a[i].id + n, a[i - 1].id + n, (a[i].x - a[i - 1].x) * 2);
}
for(int i = 1; i <= n; i++)
add(i, i + n, 1), add(i + n, i, 1);
add(n - 1, n - 1 + n, 0);
add(n - 1 + n, n - 1, 0);
add(n, n + n, 0);
add(n + n, n, 0);
memset(dis, 0x3f, sizeof(dis));
priority_queue<Node> que;
dis[n - 1] = 0, que.push((Node){0, n - 1});
while(que.size())
{
int now = que.top().pos;
que.pop();
if(vis[now]) continue;
vis[now] = 1;
for(int i = h[now]; i != 0; i = e[i].next)
if(dis[now] + e[i].dis < dis[e[i].to])
{
dis[e[i].to] = dis[now] + e[i].dis;
que.push((Node){dis[e[i].to], e[i].to});
}
}
if(dis[n] == 0x3f3f3f3f && dis[n + n] == 0x3f3f3f3f)
{cout << -1; return 0;}
cout << min(dis[n], dis[n + n]);
return 0;
}