Solution [JSOI2007]重要的城市
题目大意:给定一张带权无向图,求删去哪些点会使得某对点之间的最短路变长(或者无法到达)
最短路计数
分析:从每个源点(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 << '
';
return 0;
}