蒟蒻的唐氏做法
查看原帖
蒟蒻的唐氏做法
681229
Your_Name楼主2024/11/11 13:40

就是在跑 Floyd 的时候记录当前最小值是在哪个中转点取到的,记为 g[i][j]g[i][j]

然后如果用别的中转点又跑到了一样的长度就把原来那个删了。

最后去重就行。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 210;
multiset<int> ans;
set<int> s;
int n, m, f[N][N], INF = 1e9, g[N][N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            f[i][j] = INF;
        }
        f[i][i] = 0;
    }
    while(m --){
        int u, v, w;
        cin >> u >> v >> w;
        f[u][v] = f[v][u] = w;
    }
    for(int k = 1; k <= n; k ++){
        for(int i = 1; i <= n; i ++){
            if(i == k)continue;
            for(int j = i; j <= n; j ++){
                if(j == k || j == i)continue;
                if(f[i][j] > f[i][k] + f[k][j]){
                    f[j][i] = f[i][j] = f[i][k] + f[k][j];
                    if(ans.find(g[i][j]) != ans.end() && g[i][j] != 0)ans.erase(ans.find(g[i][j]));
                    g[i][j] = g[j][i] = k;                   
                    ans.insert(k);
                }else if(f[i][j] == f[i][k] + f[k][j] && ans.find(g[i][j]) != ans.end() && g[i][j] != 0){
                    ans.erase(ans.find(g[i][j]));
                    g[i][j] = g[j][i] = 0;
                }
            }
        }
    }
    for(auto i : ans){
        s.insert(i);
    }
    if(s.size() == 0){
        cout << "No important cities.";
    }else for(auto j : s){
        cout << j << ' ';
    }
    return 0;
}

值得注意的是不能重复遍历,不然就全删完了。 还有用完 multiset 还要再去一遍重,不然会全 WA。

2024/11/11 13:40
加载中...