【luogu P8063】Shortest paths(图论)
作者:互联网
Shortest paths
题目链接:luogu P8063
题目大意
给你一个无向图,然后给你最短路的路径,然后对于最短路上的每条边问你把它删掉之后图的最短路是多少,如果没有路径就输出 -1。
思路
(看旁边老哥开的题,麻了把自己搞不会了)
(还得看我们的 wyc 大神)
考虑怎么弄,那感性的思想家就是最短路没了找个稍微没那么差的缝起来。
那怎么缝呢,首先原来我们怎么走,对于每个点就是走最短路树得到。
那这个两边缝起来所以起点终点都都要跑。
然后你考虑删掉一条边,两个树分别会会掉落一个子树。
然后你考虑剩下的部分,有两种情况:
一种是它们之间有交集,那可以直接靠这些点连起来。
另一种就是靠边连起来(然后注意一下不能是你删掉的边),然后你看看在两个集合看看能不能各自在一个里面。
然后就可以 \(O(n^2+nm)\) 求答案啦。
代码
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N = 2050;
const int M = 1e5 + 100;
struct node {
int x, y, z;
}a[M];
int n, m, S, T, w[N][N], id[N][N], wow[N];
int dis[N], sid[N], faS[N], faT[N], na, nb;
vector <int> g[N], va[N], Gs[N], Gt[N];
bool in[N], goS[N], goT[N];
priority_queue <pair<int, int> > q;
void Dij(int S, int *f, int *fa) {
memset(in, 0, sizeof(in));
while (!q.empty()) q.pop();
q.push(make_pair(-0, S)); f[S] = 0;
while (!q.empty()) {
int now = q.top().second; q.pop();
if (in[now]) continue; in[now] = 1;
for (int i = 0; i < g[now].size(); i++) { int x = g[now][i], val = va[now][i];
if (f[x] > f[now] + val) {
f[x] = f[now] + val; q.push(make_pair(-f[x], x)); fa[x] = now;
}
}
}
}
void Init() {
memset(dis, 0x7f, sizeof(dis)); memset(sid, 0x7f, sizeof(sid));
Dij(S, dis, faS); Dij(T, sid, faT);
for (int i = 1; i <= n; i++) if (i != S) Gs[faS[i]].push_back(i);
for (int i = 1; i <= n; i++) if (i != T) Gt[faT[i]].push_back(i);
}
bool check(int x, int y) {
if (x == na && y == nb) return 0;
if (x == nb && y == na) return 0;
return 1;
}
int clac() {
memset(goS, 0, sizeof(goS)); memset(goT, 0, sizeof(goT));
queue <int> q;
q.push(S);
while (!q.empty()) {
int now = q.front(); q.pop();
goS[now] = 1;
for (int i = 0; i < Gs[now].size(); i++) { int x = Gs[now][i];
if (check(now, x)) q.push(x);
}
}
q.push(T);
while (!q.empty()) {
int now = q.front(); q.pop();
goT[now] = 1;
for (int i = 0; i < Gt[now].size(); i++) { int x = Gt[now][i];
if (check(now, x)) q.push(x);
}
}
int ans = 2e9;
for (int i = 1; i <= n; i++) if (goS[i] && goT[i]) ans = min(ans, dis[i] + sid[i]);
for (int i = 1; i <= m; i++) {
if (!check(a[i].x, a[i].y)) continue;
if (goS[a[i].x] && goT[a[i].y]) ans = min(ans, dis[a[i].x] + a[i].z + sid[a[i].y]);
if (goS[a[i].y] && goT[a[i].x]) ans = min(ans, dis[a[i].y] + a[i].z + sid[a[i].x]);
}
return (ans == 2e9) ? -1 : ans;
}
int main() {
scanf("%d %d %d %d", &n, &m, &S, &T);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].z);
w[a[i].x][a[i].y] = w[a[i].y][a[i].x] = a[i].z;
id[a[i].x][a[i].y] = id[a[i].y][a[i].x] = i;
g[a[i].x].push_back(a[i].y); g[a[i].y].push_back(a[i].x);
va[a[i].x].push_back(a[i].z); va[a[i].y].push_back(a[i].z);
}
scanf("%d", &wow[0]); for (int i = 1; i <= wow[0]; i++) scanf("%d", &wow[i]);
Init();
for (int i = 2; i <= wow[0]; i++) {
na = wow[i - 1]; nb = wow[i];
printf("%d\n", clac());
}
return 0;
}
标签:include,int,luogu,pop,push,now,P8063,Shortest,dis 来源: https://www.cnblogs.com/Sakura-TJH/p/luogu_P8063.html