第1題: bupt 1460 游覽路線
這樣可以得出算法的大致輪廓:在加入點k前更新dist[i,j]
但是問題是,此時的中間點只有1..k-1,那后面的點k+1..n會不會漏處理呢?
本質上,這題求的是環的長度,而不是路徑長度.因此,假如存在一個更短的環,它路徑上有k之后的點p1,p2,...,pm,設其中最后處理的那個點是pl.那么這個環一定會在向中間點集中加入pl的那次循環里枚舉到.
因此不存在漏解問題.
代碼如下:
1 #include <iostream>
2 using namespace std;
3 int N,M,ans;
4 //w是原圖矩陣,d是floyd最短路矩陣
5 int w[110][110],d[110][110];
6 int main(){
7 int i,j,k,a,b,c;
8 while(scanf("%d%d",&N,&M)!=EOF){
9 for(i=1;i<=N;i++)
10 for(j=1;j<=N;j++)
11 w[i][j]=d[i][j]=0;
12 for(i=1;i<=M;i++){
13 scanf("%d%d%d",&a,&b,&c);
14 if(!w[a][b]||c<w[a][b]){
15 w[a][b]=w[b][a]=c;
16 d[a][b]=d[b][a]=c;
17 }
18 }
19 ans=0x7fffffff;
20 for(k=1;k<=N;k++){
21 //先枚舉map[i,k]+map[k,j]+floyd[i,j]
22 for(i=1;i<k;i++)
23 for(j=i+1;j<k;j++)
24 if(w[i][k]&&w[k][j]&&d[i][j])
25 ans=min(ans,d[i][j]+w[i][k]+w[k][j]);
26 //再向中間點集中加入k并更新floyd矩陣
27 for(i=1;i<=N;i++){
28 if(!d[i][k])continue;
29 for(j=1;j<=N;j++){
30 if(!d[k][j]||i==j)continue;
31 if(!d[i][j]||d[i][j]>d[i][k]+d[k][j])
32 d[i][j]=d[i][k]+d[k][j];
33 }
34 }
35 }
36 if(ans<0x7fffffff)
37 printf("%d\n",ans);
38 else
39 puts("No solution.");
40 }
41 return 0;
42 }
2 using namespace std;
3 int N,M,ans;
4 //w是原圖矩陣,d是floyd最短路矩陣
5 int w[110][110],d[110][110];
6 int main(){
7 int i,j,k,a,b,c;
8 while(scanf("%d%d",&N,&M)!=EOF){
9 for(i=1;i<=N;i++)
10 for(j=1;j<=N;j++)
11 w[i][j]=d[i][j]=0;
12 for(i=1;i<=M;i++){
13 scanf("%d%d%d",&a,&b,&c);
14 if(!w[a][b]||c<w[a][b]){
15 w[a][b]=w[b][a]=c;
16 d[a][b]=d[b][a]=c;
17 }
18 }
19 ans=0x7fffffff;
20 for(k=1;k<=N;k++){
21 //先枚舉map[i,k]+map[k,j]+floyd[i,j]
22 for(i=1;i<k;i++)
23 for(j=i+1;j<k;j++)
24 if(w[i][k]&&w[k][j]&&d[i][j])
25 ans=min(ans,d[i][j]+w[i][k]+w[k][j]);
26 //再向中間點集中加入k并更新floyd矩陣
27 for(i=1;i<=N;i++){
28 if(!d[i][k])continue;
29 for(j=1;j<=N;j++){
30 if(!d[k][j]||i==j)continue;
31 if(!d[i][j]||d[i][j]>d[i][k]+d[k][j])
32 d[i][j]=d[i][k]+d[k][j];
33 }
34 }
35 }
36 if(ans<0x7fffffff)
37 printf("%d\n",ans);
38 else
39 puts("No solution.");
40 }
41 return 0;
42 }


