• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【Floyd】AtCoder ABC286 E.Souvenir

题目

https://atcoder.jp/contests/abc286/tasks/abc286_e

题意

共 \(n(2 \leq n \leq 300)\) 个城市,对于每个城市输入 \(A_i(1 \leq A_i \leq 10^9)\) 代表该城市的值;

随后输入一张 \(n \times n\) 的图 \(a\),若 \(a_{i,j} = Y\) 代表该图存在一条从城市 \(i\) 到城市 \(j\) 的有向边,边长为 \(1\),若 \(a_{i,j} = N\) 则表示没边。

输入一个正整数 \(q(1 \leq q \leq n \times (n-1))\),代表进行 \(q\) 次询问:每次询问,输入两个城市编号 \(u, v(1 \leq u, v \leq n)\),保证 \(u != v\),若城市 \(u\) 无法通过某个路径抵达城市 \(v\),则输出"Impossible",否则输出 \(s, t\),其中 \(s\) 代表从 \(u\) 到 \(v\) 的最短路径长度,\(t\) 代表从 \(u\) 到 \(v\) 的最短路径中城市的值之和的最大值。

题解

对于最短路,只需要使用 Floyd 算法进行维护。

对于路径上的节点值之和的最大值,先创建一张 \(n \times n\) 的图 \(w\),将 \(A_i\) 赋值给 \(w_{i,i}\),随后根据 \(a\) 中值为 \(a_{j,k} = Y\) 初始化出 \(w_{j,k} = w_{j,j} + w_{k,k}\)。

Floyd 算法的执行过程中,每次都是尝试引入一个节点作为中转节点。对于城市 \(i\) 和城市 \(j\),若引入城市 \(k\) 作为中转节点,城市的值的大小便是 \(w_{i,k} + w_{k,j} - w_{k,k}\),需要减去一份中转节点的值 \(w_{k,k}\) 的原因是路径 \({i,k}\) 和 \({k,j}\) 已经各自包含了一次节点 \(k\) 的值。

参考代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

constexpr ll INF = 1e18;
int n, q, x, y;
char c;
ll d[300][300], p[300][300];

void floyd() {
	for (int k = 0; k < n; ++ k) {
		for (int i = 0; i < n; ++ i) {
			if (i == k || d[i][k] == INF) continue;
			for (int j = 0; j < n; ++ j) {
				if (i == j || k == j || d[k][j] == INF) continue;
				ll sum = d[i][k] + d[k][j];
				if (sum < d[i][j]) {
					d[i][j] = sum;
					p[i][j] = p[i][k] + p[k][j] - p[k][k];
				} else if (sum == d[i][j]) {
					p[i][j] = max(p[i][j], p[i][k] + p[k][j] - p[k][k]);
				}
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
	cin >> n;
	for (int i = 0; i < n; ++ i) cin >> p[i][i];
	for (int i = 0; i < n; ++ i) {
		for (int j = 0; j < n; ++ j) {
			cin >> c;
			if (c == 'Y') {
				d[i][j] = 1;
				p[i][j] = p[i][i] + p[j][j];
			} else d[i][j] = INF;
		}
	}
	floyd();
	cin >> q;
	while (q --) {
		cin >> x >> y;
		-- x, -- y;
		if (d[x][y] == INF) cout << "Impossible\n";
		else cout << d[x][y] << ' ' << p[x][y] << '\n';
	}
}

posted on 2025-04-05 11:53  RomanLin  阅读(30)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3