重要的城市(图论 最短路)

分析

a ≠ b的从a到B的最短路,才有重要城市。

求出最短路,才能确定重要城市。

是多源最短路,n ≤ 200,可用Floyd。

若a到b,只有一条最短路,那么 a到b的路径上的点(除了a、b)都是重要城市,若a到b有多条最短路,某个城市有多条a到b的最短路经过,那么该城市为重要城市。

一边求最短路,一边求重要城市:

  • result[i][j] = 从i到j的重要城市的二进制表示,用二进制数的每一位对应一个城市,若二进制位为1,该城市是重要城市,若二进制位为0,该城市不是重要城市。
  • minDist[i][k] + minDist[k][j] < minDist[i][j],result[i][j] = (result[i][k] | result[k][j]),从i到k再从k到j是i到j的最短路,i到k的重要城市和k到j的重要城市都是i到j的重要城市。
  • minDist[i][k] + minDist[k][j] == minDist[i][j],result[i][j] = result[i][j] & (result[i][k] | result[k][j]),此时从i到j有多条最短路,这些最短路共同经过的点是重要城市。

代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <bitset>
#include <cmath>
using namespace std;

typedef long long LL;

const LL MVal = 1e14;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    LL n, m, u, v, w;
    cin >> n >> m;
    vector<vector<LL> > minDist(n + 1, vector<LL> (n + 1, MVal));
    vector<vector<bitset<210> > > result(n + 1, vector<bitset<210> > (n + 1, 0));

    for (LL i = 1; i <= m; ++i) {
        cin >> u >> v >> w;
        minDist[u][v] = w;
        minDist[v][u] = w;
    }
    for (LL i = 1; i <= n; ++i)  minDist[i][i] = 0;

    for (LL k = 1; k <= n; ++k) {
        for (LL i = 1; i <= n; ++i) {
            for (LL j = 1; j <= n; ++j) {
                if (i != j && minDist[i][k] + minDist[k][j] < minDist[i][j]) {
                    minDist[i][j] = minDist[i][k] + minDist[k][j];
                    result[i][j] = (result[i][k] | result[k][j]);
                    if (result[i][j] == 0 && result[j][k] == 0)  result[i][j][k - 1] = 1;
                } else if (i != j && minDist[i][k] + minDist[k][j] == minDist[i][j]) {
                    result[i][j] = (result[i][j] & (result[i][k] | result[k][j]));
                }
            }
        }
    }

    bitset<210> res(0);
    for (LL i = 1; i <= n; ++i) {
        for (LL j = 1; j <= n; ++j) {
            if (i != j)  res |= result[i][j];
        }
    }

    if (res == 0)  cout << "No important cities.";
    else {
        for (LL i = 0; i < n; ++i)
            if (res[i] == 1)  cout << (i + 1) << ' ';
    }

    return 0;
}

总结

1.多源最短路且边权不等,且O(n^3)不会TLE,用Floyd。

2.转化为二进制可减少空间和时间,若数据范围太大不能用整数表示,可用bitset。

相关推荐
2301_795167201 小时前
玩转Rust高级应用 如何避免对空指针做“解引用”操作,在C/C++ 里面就是未定义行为
c语言·c++·rust
智驱力人工智能3 小时前
基于视觉分析的人脸联动使用手机检测系统 智能安全管理新突破 人脸与手机行为联动检测 多模态融合人脸与手机行为分析模型
算法·安全·目标检测·计算机视觉·智能手机·视觉检测·边缘计算
2301_764441333 小时前
水星热演化核幔耦合数值模拟
python·算法·数学建模
循环过三天3 小时前
3.4、Python-集合
开发语言·笔记·python·学习·算法
priority_key6 小时前
排序算法:堆排序、快速排序、归并排序
java·后端·算法·排序算法·归并排序·堆排序·快速排序
不染尘.6 小时前
2025_11_7_刷题
开发语言·c++·vscode·算法
似水এ᭄往昔6 小时前
【C++】--stack和queue
开发语言·c++
仰望—星空7 小时前
MiniEngine学习笔记 : CommandListManager
c++·windows·笔记·学习·cg·direct3d
来荔枝一大筐7 小时前
力扣 寻找两个正序数组的中位数
算法
算法与编程之美7 小时前
理解Java finalize函数
java·开发语言·jvm·算法