1. 程式人生 > >解題:JSOI 2007 重要的城市

解題:JSOI 2007 重要的城市

lan sed gin 更新 scanf sca sin mem ==

題面

考慮一個點$x$,如果某兩個點$u,v$間的所有最短路都經過$x$,那麽$x$肯定是重要的。這個題$n$比較小,所以我們直接跑floyd,在過程中記錄

當發生松弛時,我們具體討論:

如果這個長度是兩點間新更新出的一條最短路,即$dis[i][j]>dis[i][k]+dis[k][j]$,我們在$i,j$的路徑上記錄$k$這個點

如果這是一條長度在以前更新過的最短路,那麽說明兩點間不只有一條最短路,原來的那個點已經廢了,更新一下

技術分享圖片
 1 #include<set>
 2 #include<cstdio>
 3 #include<cstring>
 4
#include<algorithm> 5 using namespace std; 6 const int N=205; 7 int mat[N][N],imp[N][N]; 8 int n,m,t1,t2,t3; 9 set<int> ss; 10 int main () 11 { 12 scanf("%d%d",&n,&m); 13 memset(mat,0x3f,sizeof mat); 14 for(int i=1;i<=n;i++) mat[i][i]=0; 15 for(int i=1;i<=m;i++)
16 { 17 scanf("%d%d%d",&t1,&t2,&t3); 18 mat[t1][t2]=mat[t2][t1]=t3; 19 } 20 for(int k=1;k<=n;k++) 21 for(int i=1;i<=n;i++) 22 for(int j=1;j<=n;j++) 23 if(i!=j&&i!=k&&j!=k) 24 { 25 if
(mat[i][j]>mat[i][k]+mat[k][j]) 26 mat[i][j]=mat[i][k]+mat[k][j],imp[i][j]=k; 27 else if(mat[i][j]==mat[i][k]+mat[k][j]) 28 imp[i][j]=0; 29 } 30 for(int i=1;i<=n;i++) 31 for(int j=1;j<=n;j++) 32 if(imp[i][j]) ss.insert(imp[i][j]); 33 if(ss.empty()) printf("No important cities."); 34 while(!ss.empty()) 35 printf("%d ",*ss.begin()),ss.erase(ss.begin()); 36 return 0; 37 }
View Code

解題:JSOI 2007 重要的城市