题目链接

题目大意:给定一张带权无向图,求删去哪些点会使得某对点之间的最短路变长(或者无法到达)

最短路计数


分析:从每个源点\(u\)出发跑单源最短路,如果\(u\)到一个点\(v\)之间的最短路只有\(1\)条,那么\(u,v\)之间的所有点(不含\(u,v\))都是答案

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 256;
struct Edge{
    int to,dist;
};
struct Node{
    int u,h;
    bool operator < (const Node &rhs)const{return h > rhs.h;}
};
vector<Edge> G[maxn];
inline void addedge(int from,int to,int dist){G[from].push_back(Edge{to,dist});}
int n,m,ans[maxn],vis[maxn],dis[maxn],cnt[maxn],faz[maxn],flag;
inline void solve(int s){
    priority_queue<Node> Q;
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    memset(cnt,0,sizeof(cnt));
    memset(faz,0,sizeof(faz));
    dis[s] = 0;
    Q.push(Node{s,0});
    while(!Q.empty()){
        int u = Q.top().u;Q.pop();
        if(vis[u])continue;
        vis[u] = 1;
        for(auto e : G[u]){
            if(dis[u] + e.dist < dis[e.to])dis[e.to] = dis[u] + e.dist,faz[e.to] = u,cnt[e.to] = cnt[u],Q.push(Node{e.to,dis[e.to]});
            else if(dis[u] + e.dist == dis[e.to])cnt[e.to]++;
        }
    }
    for(int u = 1;u <= n;u++)
        if(!cnt[u] && u != s)
            for(int now = faz[u];now != s;now = faz[now])
                ans[now] = 1;
}
int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for(int u,v,d,i = 1;i <= m;i++)
        cin >> u >> v >> d,addedge(u,v,d),addedge(v,u,d);
    for(int i = 1;i <= n;i++)solve(i);
    for(int i = 1;i <= n;i++)
        if(ans[i])cout << i << " ",flag = 1;
    if(!flag)cout << "No important cities.";
    cout << '\n';
    return 0;
}

相关文章: