1030 Travel Plan(考察Dijkstra内嵌第二标尺或Dijkstra+DFS)

 大致题意就是。。。懒得说了。

这是一道模板题,要先记住大体流程,然后反复练习。

方法一:Dijlstra内嵌第二标尺

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn = 510;
 5 const int inf = 0x3fffffff;
 6 int G[maxn][maxn];//邻接矩阵、边权
 7 bool visited[maxn] = {false};//标记已访问数组
 8 
 9 int d[maxn];//从起点S到其它顶点的最短距离
10 int pre[maxn];//起点S到终点D的路径
11 
12 int cost[maxn][maxn];//边的费用
13 int c[maxn]; //从起点S到其它顶点的最少费用
14 int n,m,st,ed;
15 
16 void dijkstra(int s) {
17     //第一步,初始化d[]、c[]、pre[]
18     fill(visited,visited+maxn,false);
19     fill(d,d+maxn,inf);
20     fill(c,c+maxn,inf);
21     for(int i = 0; i < n ; ++i) pre[i] = i;
22     d[s] = 0;
23     c[s] = 0;
24     //第二步,循环n次
25     for(int i = 0; i < n; ++i) {
26         //第三步,遍历所有顶点u,找出最小d[u],并标记u已被访问
27         int u = -1,MIN = inf;
28         for(int j = 0; j < n; ++j) {
29             if(visited[j] == false && MIN > d[j]) {
30                 u = j;
31                 MIN = d[j];
32             }
33         }
34         if(u == -1) return ;
35         visited[u] = true;
36         //第四步,遍历所有顶点v,用顶点u更新d[v]、C
37         for(int v = 0; v < n; ++v) {
38             if(visited[v] == false && G[u][v] != inf) {
39                 if(d[u] + G[u][v] < d[v]) {
40                     d[v] = d[u] + G[u][v];
41                     c[v] = c[u]+ cost[u][v];
42                     pre[v] = u;
43                 } else if(d[u] + G[u][v] == d[v]) {
44                     if(c[u]+ cost[u][v] < c[v]) {
45                         c[v] = c[u]+ cost[u][v];
46                         pre[v] = u;
47                     }
48                 }
49             }
50         }
51     }
52 }
53 
54 void DFS(int v) { //打印起点到终点的最短路径
55     if(v == st) {//找到起点,即叶子结点
56         printf("%d",v);
57         return ;
58     }
59     DFS(pre[v]);//递归访问v的前驱顶点pre[v]
60     printf(" %d",v);
61 }
62 int main() {
63     cin>>n>>m>>st>>ed;
64     //初始化G
65     fill(G[0],G[0]+maxn*maxn,inf);
66     int u,v;
67     for(int i = 0; i < m; ++i) {
68         cin>>u>>v;
69         cin>>G[u][v]>>cost[u][v];
70         G[v][u]= G[u][v];
71         cost[v][u] = cost[u][v];
72     }
73     dijkstra(st);//算法入口
74     DFS(ed);//打印起点st到终点ed的路径
75     printf(" %d %d",d[ed],c[ed]);
76     return 0;
77 }

 方法二:Dijkstra+DFS

 1 #include<iostream>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 510;
 6 const int inf = 0x3fffffff;
 7 //图的要素
 8 int G[maxn][maxn];//邻接矩阵、边权
 9 bool visited[maxn] = {false};//标记已访问数组
10 
11 //迪杰斯特拉的要素
12 int d[maxn];//从起点S到其它顶点的最短距离
13 vector<int> pre[maxn]; //存放结点的前驱结点
14 
15 //第二标尺的要素
16 int cost[maxn][maxn];//边的费用
17 int mincost = inf; //总的最少费用
18 vector<int> path,tempPath;
19 
20 int n,m,st,ed;
21 
22 void dijkstra(int s) {
23     //第一步,初始化d[]
24     fill(visited,visited+maxn,false);
25     fill(d,d+maxn,inf);
26     d[s] = 0;
27     //第二步,循环n次
28     for(int i = 0; i < n; ++i) {
29         //第三步,遍历所有顶点u,找出最小d[u],并标记u已被访问
30         int u = -1,MIN = inf;
31         for(int j = 0; j < n; ++j) {
32             if(visited[j] == false && MIN > d[j]) {
33                 u = j;
34                 MIN = d[j];
35             }
36         }
37         if(u == -1) return ;
38         visited[u] = true;
39         //第四步,遍历所有顶点v,用顶点u更新d[v]、pre
40         for(int v = 0; v < n; ++v) {
41             if(visited[v] == false && G[u][v] != inf) {
42                 if(d[u] + G[u][v] < d[v]) {
43                     d[v] = d[u] + G[u][v];
44                     pre[v].clear();
45                     pre[v].push_back(u);// u为 v的前驱
46                 } else if(d[u] + G[u][v] == d[v]) {
47                     pre[v].push_back(u);// u为 v的前驱之一
48                 }
49             }
50         }
51     }
52 }
53 
54 void DFS(int v) { //v为当前结点
55     //递归边界
56     if(v == st) {//找到叶子结点
57         tempPath.push_back(v);
58         //边权之和
59         int tempcost = 0;
60         for(int i = tempPath.size()-1; i > 0; --i) {
61             int u = tempPath[i],v = tempPath[i-1];
62             tempcost += cost[u][v];
63         }
64         if(tempcost < mincost) {
65             mincost = tempcost;
66             path = tempPath;
67         }
68         tempPath.pop_back();
69         return ;
70     }
71     tempPath.push_back(v);
72     for(int i = 0; i < pre[v].size(); ++i) //遍历顶点v的前驱、或称孩子结点
73         DFS(pre[v][i]);
74     tempPath.pop_back();
75 }
76 int main() {
77     cin>>n>>m>>st>>ed;
78     //初始化G
79     fill(G[0],G[0]+maxn*maxn,inf);
80     int u,v;
81     for(int i = 0; i < m; ++i) {
82         cin>>u>>v;
83         cin>>G[u][v]>>cost[u][v];
84         G[v][u]= G[u][v];
85         cost[v][u] = cost[u][v];
86     }
87     dijkstra(st);//算法入口
88     DFS(ed);//获取最优路径
89     for(int i = path.size()-1; i>=0; --i)
90         printf("%d ",path[i]); //倒着打印最短路径
91     printf("%d %d",d[ed],mincost);
92     return 0;
93 }

 

posted @ 2020-03-08 09:50  tangq123  阅读(136)  评论(0)    收藏  举报