[JSOI2007]重要的城市(x)
题目:洛谷P1841。
题目大意:如果一个城市c在城市a到b($a\neq b\neq c$)的最短路中,并且去掉c最短路就会变短,那么称c为重要的城市。
现在要你按次序输出所有重要的城市。如果没有,输出“No important cities.”(引号不必输出)。
解题思路:跑Floyd,并记录两点间的一个重要的城市。
如果两个点的距离更新,则重要的城市也更新。
如果两个点的距离在计算时出现与原来结果相等时,就说明可能出现多条最短路,这时删掉重要的城市。
最后枚举两个点,把它们之间的重要的城市去重后记录下来,排序输出即可。
由于在Floyd中,对于每个中点,其他点对都进行过考虑,因此答案是不会出现遗漏的。
时间复杂度$O(n^3)$。
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> int n,m,d[202][202],s[202][202],ans[202]; bool has[202]; inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); return d; } int main(){ n=readint(),m=readint(); memset(d,0x3f,sizeof d); while(m--){ int x=readint(),y=readint(),z=readint(); d[x][y]=d[y][x]=z; } for(int k=1;k<=n;++k) for(int i=1;i<=n;++i) if(i!=k) for(int j=1;j<=n;++j) if(i!=j&&j!=k){ if(d[i][j]>d[i][k]+d[k][j]){ d[i][j]=d[i][k]+d[k][j]; s[i][j]=k; }else if(d[i][j]==d[i][k]+d[k][j])s[i][j]=-1; } int cnt=0; memset(has,0,sizeof has); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(s[i][j]>0&&!has[s[i][j]]){ has[s[i][j]]=true; ans[++cnt]=s[i][j]; } if(cnt==0)return puts("No important cities."),0; std::sort(ans+1,ans+cnt+1); for(int i=1;i<cnt;++i)printf("%d ",ans[i]); printf("%d\n",ans[cnt]); return 0; }