UESTCoj 265 War(Floyd最短路)

题目描述:Your country is now involved in a war! In the front, there are  N  positions between which you can transfer goods. Unfortunately the enemies will attack you and destroy some positions. When transferring, you cannot pass through a position which has been destroyed. As the commander of the army, you want to know the minimum distance between some position  u  and  v , after some positions have been destroyed.

Floyd算法求最短路的原理是枚举每个点做为中点,更新起点和终点的最短距离。
按照题意中的意思是要拆除一些点后再求最短路,我们可以倒着去做认为是新建一些点后再去求最短路,对于每个新建点k,我们只要以k为中点更新一下最短路就行了,更新的过程是O(n^2)的。然后最多新建n个点,所以整个算法复杂度为O(n^3)。
PS:我觉得暴力SPFA应该可以过的,然后就T了。
#pragma warning(disable:4996)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

int dis[205][205];
bool exist[205];
vector<int>ans;
int query[10005], x[10005], y[10005];

int n, m;

int main(){
	int t; scanf("%d", &t);
	while (t--){
		scanf("%d %d", &n, &m);
		memset(dis, 0x3f, sizeof dis);
		memset(exist, true, sizeof exist);
		for (int i = 1; i <= n; i++)dis[i][i] = 0;
		for (int i = 0; i < m; i++){
			int u, v, c; scanf("%d %d %d", &u, &v, &c);
			dis[u][v] = dis[v][u] = min(dis[u][v], c);
		}

		int q; scanf("%d", &q);
		for (int i = 1; i <= q; i++){
			int op; scanf("%d", &op);
			if (op == 0){
				int u, v; scanf("%d %d", &u, &v);
				query[i] = 0;
				x[i] = u;
				y[i] = v;
			}
			else if (op == 1){
				int u; scanf("%d", &u);
				exist[u] = false;
				query[i] = 1;
				x[i] = u;
			}
		}
		//Floyd求出最短路
		for (int k = 1; k <= n; k++){
			if (!exist[k])continue;
			for (int i = 1; i <= n; i++){
				for (int j = 1; j <= n; j++){
					dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
				}
			}
		}

		ans.clear();
		for (int i = q; i >= 1; i--){
			if (query[i] == 0){
				if (exist[x[i]] && exist[y[i]]){
					int tmp = dis[x[i]][y[i]];
					tmp = tmp == dis[0][0] ? -1 : tmp;
					ans.push_back(tmp);
				}
				else ans.push_back(-1);
			}
			//加点
			else if (query[i] == 1){
				int k = x[i];
				exist[k] = true;
				for (int i = 1; i <= n; i++){
					for (int j = 1; j <= n; j++){
						dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
					}
				}
			}
		}
		for (int i = (int)ans.size() - 1; i >= 0; i--){
			printf("%d\n", ans[i]);
		}
		puts("");
	}
	return 0;
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值