分层图
-
这个题目需要大家了解分层图。其实只要了解分层图了这个题目也就解决了。
-
边权为 0 0 0 的边不能走 1 1 1 的边可以走。其中还有几个点可以将边权反转。根据这几个条件我们就很容易想到边权为 0 0 0 的边为一层,边权为 1 1 1 的边为一层,可以进行反转的点为这两层图的公共点。
-
根据上述分析我们就很容易建立两层图。但是需要注意,边权为 0 0 0 的建立一层时,我们建图的时候建立的边权为 1 1 1 ,因为我们要想去到边权为 0 0 0 的层,那么必须进行翻转,既然反转了那么为 0 0 0 的边权就变为了 1 1 1 。
-
之后给定几个可以反转边权的点,那么这几个点就是连接两层图之间的点,这个边的边权会给的。建立完图之后那么需要知道最短路,那么直接跑最短路算法就好了。最后需要判断连个终点,这也是分层图的特点。
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 500010 * 2, M = N * 2;
int S, T;
int d[N];
int n, m, k;
bool is_de[N];
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int c) {
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx ++ ;
}
void dijkstra() {
memset(d, 0x3f, sizeof d);
d[S] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> q;
q.emplace(0, S);
while (!q.empty()) {
int t = q.top().second;
q.pop();
if (is_de[t]) continue;
is_de[t] = true;
for (int i = h[t]; i != -1; i = ne[i]) {
int j = e[i];
if (d[j] > d[t] + w[i]) {
d[j] = d[t] + w[i];
q.emplace(d[j], j);
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
memset(h, -1, sizeof h);
cin >> n >> m >> k;
while (m -- ) {
int a, b, c;
cin >> a >> b >> c;
if (c) {
add(a, b, 1);
add(b, a, 1);
} else {
add(a + n, b + n, 1);
add(b + n, a + n, 1);
}
}
while (k -- ) {
int x, t;
cin >> x >> t;
add(x, x + n, t);
add(x + n, x, t);
}
cin >> S >> T;
dijkstra();
int res = min(d[T], d[n + T]);
if (res == 0x3f3f3f3f) res = -1;
cout << res << endl;
return 0;
}