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 }


浙公网安备 33010602011771号