ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【luogu P8063】Shortest paths(图论)

2022-07-18 15:34:12  阅读:154  来源: 互联网

标签:include int luogu pop push now P8063 Shortest dis


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有