Skip to content

Commit f70de98

Browse files
authored
Create 最短路径
1 parent a8f64f1 commit f70de98

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed

最短路径

+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
Sample - Greediness
2+
http://acm.hdu.edu.cn/showproblem.php?pid=3790
3+
贪心典型题(2)- 最短路径
4+
题目描述
5+
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
6+
输入格式
7+
输入n, m,点的编号是1~n, 然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s, t;
8+
起点s,终点t。n和m为0时输入结束。 (1< n <=1000, 0< m <100000, s != t)
9+
输出格式
10+
输出 一行有两个数, 最短距离及其花费。
11+
样例输入
12+
13+
3 2
14+
1 2 5 6
15+
2 3 4 5
16+
1 3
17+
0 0
18+
19+
样例输出
20+
21+
9 11
22+
下载资料:
23+
输入文件
24+
输出文件
25+
参考答案
26+
/***************************************************************************
27+
版权申明:本程序为北京交通大学《算法设计与分析》课程以及教材《算法设计与问题
28+
求解-编程实践》的教辅材料,著作权为北京交通大学计算机与信息技术学院视觉智能
29+
实验室李清勇教授所有,禁止用于任何盈利性质的商业行为。未经著作权所有人允许,
30+
禁止进行传播和出版。
31+
*************************************************************************/
32+
33+
/**************************************************************************
34+
解题思路:迪克斯切算法
35+
36+
**************************************************************************/
37+
38+
39+
/**********code2*******/
40+
#include <bits/stdc++.h>
41+
using namespace std;
42+
43+
const int N = 1e3+233;
44+
const int inf = 0x3f3f3f3f;
45+
int matd[N][N]; ///存图-路径
46+
int matp[N][N]; ///存图-花费
47+
int path[N][N]; ///记录路径数组
48+
int disd[N]; ///从源点s出发的最短路径
49+
int disp[N]; ///从源点s出发的最短花费
50+
int vis[N]; ///标记已经使用过的图
51+
int numvex,numline,n,m,s,t,a,b,d,p;
52+
void Dijkstra(int s,int t)
53+
{
54+
int cur,Min;
55+
memset(vis,0,sizeof(vis));
56+
for(int i=1; i<=numvex; ++i)
57+
{
58+
disd[i]=matd[s][i];
59+
disp[i]=matp[s][i];
60+
}
61+
disd[s]=0;
62+
vis[s]=1;
63+
///开始主循环 每次求得v0到某个顶点v的最短路径 并加v到集合S中
64+
for(int i=1; i<=numvex; ++i)
65+
{
66+
Min=inf;
67+
for(int j=1; j<=numvex; ++j)
68+
{
69+
///核心过程--选点
70+
///如果j顶点在V-S中,这个过程最终选出的点 应该是选出当前V-S中与S有关联边且权值最小的顶点
71+
if(!vis[j] && disd[j]<=Min)
72+
{
73+
Min=disd[cur=j];
74+
}
75+
}
76+
if(Min==inf)break;
77+
///选出该点后加入到合集S中
78+
vis[cur]=1;
79+
///更新当前最短路径和距离
80+
///在此循环中 v为当前刚选入集合S中的点
81+
///则以点V为中间点 考察 d0v+dvw 是否小于 D[w] 如果小于 则更新
82+
///比如加进点 3 则若要考察 D[5] 是否要更新 就 判断 d(v0-v3) + d(v3-v5) 的和是否小于D[5]
83+
for(int k=1; k<=numvex; ++k)
84+
{
85+
if(!vis[k])
86+
{
87+
if(disd[k] > (disd[cur]+matd[cur][k]) )
88+
{
89+
disd[k]=disd[cur]+matd[cur][k];
90+
disp[k]=disp[cur]+matp[cur][k];
91+
}
92+
else if (disd[k]== (disd[cur]+matd[cur][k])) //如果路径相同
93+
{
94+
if(disp[k]>disp[cur]+matp[cur][k])
95+
{
96+
disp[k]=disp[cur]+matp[cur][k];
97+
}
98+
}
99+
}
100+
}
101+
}
102+
}
103+
104+
void init()
105+
{
106+
for(int i=0; i<N; ++i)
107+
{
108+
for(int j=0; j<N; ++j)
109+
{
110+
if(i==j) matd[i][j]=matp[i][j]=0;
111+
else matd[i][j]=matp[i][j]=inf;
112+
}
113+
}
114+
}
115+
116+
int main()
117+
{
118+
//freopen("in.txt","r",stdin);
119+
while(scanf("%d%d",&numvex,&numline),numvex||numline)
120+
{
121+
init();
122+
for(int i=0; i<numline; ++i)
123+
{
124+
scanf("%d%d%d%d",&a,&b,&d,&p);
125+
if(matd[a][b]>d)
126+
{
127+
matd[a][b]=matd[b][a]=d;
128+
matp[a][b]=matp[b][a]=p;
129+
}
130+
else if(matd[a][b]==d)
131+
{
132+
if(matp[a][b]>p)
133+
{
134+
matp[a][b]=matp[b][a]=p;
135+
}
136+
}
137+
}
138+
//cin>>s>>t;
139+
scanf("%d%d",&s,&t);
140+
Dijkstra(s,t);
141+
printf("%d %d\n",disd[t],disp[t]);
142+
}
143+
return 0;
144+
}
145+
146+
147+
148+
149+
150+
151+
152+
#include<cstdio>
153+
#include<set>
154+
#include<vector>
155+
#include<algorithm>
156+
using namespace std;
157+
///邻接表储存边 距离,花费,所达点
158+
vector<pair<pair<int,int>,int> >links[1010];
159+
///储存所有的"距离",定义为距离和花费的pair
160+
///参见以下链接
161+
///http://www.cplusplus.com/reference/utility/pair/operators/
162+
pair<int,int>dis[1010];
163+
164+
///定义"距离"的加法
165+
pair<int,int> operator + (const pair<int,int>&a, const pair<int,int>&b)
166+
{
167+
return make_pair(a.first + b.first, a.second + b.second);
168+
}
169+
int main()
170+
{
171+
for(int n,m;scanf("%d%d",&n,&m),n||m;)
172+
{
173+
for(int i=1;i<=n;i++)
174+
{
175+
links[i].clear();
176+
}
177+
for(int i=0;i<m;i++)
178+
{
179+
int a,b,d,p;
180+
scanf("%d%d%d%d",&a,&b,&d,&p);
181+
links[a].push_back(make_pair(make_pair(d,p), b) );
182+
links[b].push_back(make_pair(make_pair(d,p), a) );
183+
}
184+
int s,t;scanf("%d%d",&s,&t);
185+
///初始化距离值
186+
for(int i=1;i<=n;i++)
187+
{
188+
dis[i] = make_pair(0x3f3f3f3f,0x3f3f3f3f);
189+
}
190+
dis[s] = make_pair(0,0);
191+
///使用set达到类似priority_queue的功能
192+
set<pair<pair<int,int>,int> >que;
193+
///插入原点
194+
que.insert(make_pair(dis[s],s));
195+
while(!que.empty())
196+
{
197+
int who = que.begin()->second;
198+
pair<int,int> dist = que.begin()->first;
199+
que.erase(que.begin());
200+
///如果这个点已经被使用过,就不再更新
201+
if(dist != dis[who])
202+
continue;
203+
for(int i=0;i<links[who].size();i++)
204+
{
205+
int to = links[who][i].second;
206+
pair<int,int> len = links[who][i].first;
207+
pair<int,int> another_dis = dis[who] + len;
208+
if(dis[to] > another_dis)
209+
{
210+
dis[to] = another_dis;
211+
que.insert(make_pair(dis[to],to));
212+
}
213+
}
214+
}
215+
printf("%d %d\n",dis[t].first, dis[t].second);
216+
}
217+
}

0 commit comments

Comments
 (0)