题目描述
参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里。而食堂门前施工虽然也截断了原来通向计算中心的路,却没有使路程增加,因为可以找到同样长度的路作替代。其实,问题的关键在于,路截断的地方是交通要点。
同样的情况也出现在城市间的交通中。某些城市如果出了问题,可能会引起其他很多城市的交通不便。另一些城市则影响不到别的城市的交通。jsoi冬令营的同学发现这是一个有趣的问题,于是决定研究这个问题。
他们认为这样的城市是重要的:如果一个城市c被破坏后,存在两个不同的城市a和b(a, b均不等于c),a到b的最短距离增长了(或不通),则城市c是重要的。
jsoi冬令营的同学面对着一张教练组交给他们的城市间交通图,他们希望能找出所有重要的城市。现在就请你来解决这个问题。
我怀疑这是披着JSOI外衣的原创题QWQ,因为我不信一年一场省选会考出7道题这样的质数题目数
然后由于n很小,明显考虑先Floyd,枚举点对我们思考一个点是这个点对关键点当且仅当只有这个点可以更新最短路径但是实际这只有90分
如果一个点对的最短路径就是u-v那么不存在这种情况的关键点特判排除。
#include<bits/stdc++.h>
using namespace std;
const int N=301;
int VIP[N];
int G[N][N];
int F[N][N];
int n,m;
set<int> S;
int main(){
scanf("%d%d",&n,&m);
memset(G,0x3f,sizeof(G));
for(int i=1;i<=m;++i){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
G[u][v]=c;
G[v][u]=c;
F[u][v]=F[v][u]=c;
}
for(int k=1;k<=n;++k){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
G[i][j]=min(G[i][j],G[i][k]+G[k][j]);
}
}
}
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
int Min=G[i][j];
if(Min==F[i][j])continue;
int cnt=0;
int V=-1;
if(Min==1061109567)continue;
for(int k=1;k<=n;++k){
if(k==i||k==j)continue;
if(G[i][k]+G[k][j]==Min){
if(!cnt)cnt++,V=k;
else cnt++;
}
}
if(cnt==1)
S.insert(V);
}
}
if(S.empty()){
cout<<"No important cities.";
}
else{
set<int>::iterator It;
for(It=S.begin();It!=S.end();++It){
cout<<*It<<' ';
}
}
}