UVA 11165 - Galactic Travel
题意:给定一些不能走的边,要求出从s到t的最短路
思路:由于点数多,直接广搜会超时,所以加上优化,已经找过的点就不在重复找了,这点可以利用并查集进行优化,然后对于每个点的每个不能走的区间,可以先排序,然后利用twopointer的性质,每次可以从上次找到的位置往后找即可
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100005;
int t, n, m, parent[N], vis[N];
int find(int x) {
return x == parent[x] ? x : parent[x] = find(parent[x]);
}
struct Ban {
int v1, v2;
Ban(int v1, int v2) {
this->v1 = v1;
this->v2 = v2;
}
};
bool cmp(Ban a, Ban b) {
return a.v1 < b.v1;
}
vector<Ban> b[N];
const int INF = 0x3f3f3f3f;
int bfs(int s, int t) {
queue<int> Q;
Q.push(s);
vis[s] = 0;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
if (u == t) return vis[u];
int v = find(0);
int s = 0;
while (v < n) {
if (v == u) v = find(v + 1);
else {
int flag = 1;
for (int i = s; i < b[u].size(); i++) {
if (b[u][i].v1 <= v && b[u][i].v2 >= v) {
flag = 0;
v = find(b[u][i].v2 + 1);
s = i + 1;
break;
}
}
if (flag) {
vis[v] = vis[u] + 1;
Q.push(v);
parent[v] = find(v + 1);
v = find(v);
}
}
}
}
return -1;
}
int main() {
int cas = 0;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; i++) {
parent[i] = i;
b[i].clear();
}
int u, v1, v2;
while (m--) {
scanf("%d%d-%d", &u, &v1, &v2);
if (v1 > v2) swap(v1, v2);
b[u].push_back(Ban(v1, v2));
}
for (int i = 0; i < n; i++)
sort(b[i].begin(), b[i].end(), cmp);
int s, t;
scanf("%d%d", &s, &t);
printf("Case #%d: ", ++cas);
int tmp = bfs(s, t);
if (tmp == -1) printf("Impossible\n");
else printf("%d\n", tmp);
}
return 0;
}