Minimum Transport Cost HDU - 1385

原题链接

考察:Floyd+输出路径

错误思路:

       跑一遍Floyd,记录使g[i][j]>g[i][k]+g[k][j]+w[k] 变小的k.分为[l,k] [k,r]输出路径.

       当g[i][j] = g[i][k]+g[k][j]+w[k],比较path[i][j] 与当前枚举点k的大小.

错误原因:

        这个思路错在哪呢?当正解答案与其他路径长度相等时就容易WA.

比如这组数据:

5
0 2 4 -1 -1
-1 0 -1 -1 2
-1 -1 0 2 -1
-1 -1 -1 0 -1
-1 -1 -1 2 0
1 3 8 4 5
1 4
-1 -1
0

正解是1->2->5->4 错误程序会输出1 3 4

        实际是当k = 5时,path[1][4]记录的是[3],我们用k与3比较当然是3比较小.这是因为path中断点在路径不同位置造成的.

思路:

        Floyd预处理是正确的,但是难点在字典序上.按照思路我们应该从路径的第二个点开始比较,直到路径终点,也就是当g[i][j]被更新时,path[i][j]到底应该赋什么值?

        对于每一个区间[i,j]都比较路径第二个点的大小,那么最后扩展的区间一定是字典序最小的.

 1 #include <iostream> 
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N = 310,INF = 0x3f3f3f3f;
 7 int n,g[N][N],w[N],path[N][N],S,E;
 8 vector<int> p;
 9 void floyd()
10 {
11     for(int k=1;k<=n;k++)
12      for(int i=1;i<=n;i++)
13       for(int j=1;j<=n;j++)
14       {
15           if(g[i][k]==INF||g[k][j]==INF) continue;
16           int idx = path[i][k];
17           if(i==k) idx = j;
18           if(g[i][j]>g[i][k]+g[k][j]+w[k])
19           {
20               g[i][j] = g[i][k]+g[k][j]+w[k];
21               path[i][j] = idx;
22         }else if(g[i][j]==g[i][k]+g[k][j]+w[k]&&path[i][j]>idx) path[i][j] = idx;
23       }
24 }
25 void dfs(int l,int r)
26 {
27     int k = path[l][r];
28     if(k==r) return;
29     p.push_back(k);
30     dfs(k,r);
31 }
32 void Myprintf(int i,int j)
33 {
34     p.clear();
35     p.push_back(i);
36     dfs(i,j);
37     if(i!=j) p.push_back(j);
38 }
39 int main()
40 {
41     while(scanf("%d",&n)!=EOF&&n)
42     {
43         
44         for(int i=1;i<=n;i++)
45           for(int j=1;j<=n;j++)
46           {
47               scanf("%d",&g[i][j]);
48               if(g[i][j]==-1) g[i][j] = INF;
49               path[i][j] = j;
50           }
51         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
52         floyd();
53         while(scanf("%d%d",&S,&E)!=EOF&&S!=-1&&E!=-1)
54         {
55             if(g[S][E]==INF) continue;
56             printf("From %d to %d :\n",S,E);
57             printf("Path: ");
58             if(S!=E)
59             {
60                 Myprintf(S,E);
61                 for(int i=0;i<p.size()-1;i++)
62                 printf("%d-->",p[i]);
63                 printf("%d\n",p.back());
64                 printf("Total cost : %d\n\n",g[S][E]);
65             }else printf("%d\nTotal cost : 0\n\n",S); 
66             
67         }
68     }
69     return 0;
70 }

 

posted @ 2021-05-03 17:07  acmloser  阅读(33)  评论(0编辑  收藏  举报