您的位置:首页 > 理论基础 > 数据结构算法

sdut 3363 数据结构实验之图论七:驴友计划

2016-11-04 18:51 267 查看


数据结构实验之图论七:驴友计划

Time Limit: 1000MS Memory Limit: 65536KB

Submit Statistic Discuss


Problem Description

做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。


Input

连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。 


Output

在同一行中输出路径长度和收费总额,数据间用空格间隔。 


Example Input

1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20



Example Output

3 40



Hint

 


Author

xam 


提示

SPFA算法:

同dijkstra一样,Bellman-Ford也是处理单元最短路径的算法,可以处理负环问题。这个算法的根源思想在于:如有最短路,则每个顶点最多经过一次,这条路不超过n-1条边,长度为k的路可能由长度为k-1的路增加一条边得到。每一个最短路dis[i]可能由dis[j]+edge[i][j]得到,也可能不变。根据这个原理,这个过程就能容易地写出来。

for(i=1;i<V;i++)
for(j=0;j<E;j++)
if(dis[G[j].v]>dis[G[i].u]+G[i].c)
relax(G[j].u,G[j].v,G[j].c);
为什么能够判断负环?根据原理,每个最短路都不会超过n-1条边,如果说超过了n-1条边的话,那么就说明走了重点,即走了环,因此就可以知道里面产生了负环,才使得这个最短路无解,那么如何判断负环?其实操作完这个过程后只要再进行一次松弛操作,如果发现还有点松弛的话,那么就说明产生了负环,这个问题也就解决了。SPFA对这个算法很好地进行了优化。
优化的根源在于,能够改变最短路的路径都是之前成功松弛过的点,也就是说,如果一个点被成功地松弛了,那么这个点才有可能松弛其他边,没有被松弛的点,就说明这个点所记录的最短路径没有被改变,那么以这个点为起点的边都不可能被松弛,所以具体的实现就是造一个队列,把成功松弛的点放入队列之中等待松弛,直到队列中没有点了,说明整个最短路的过程就结束了。
这个算法的期望时间复杂度是O(kE),一般情况下,k是一个常数且很小,所以这个算法拥有快速求取最短路的作用。


示例程序

#include <stdio.h>
#include <string.h>
#define MAX 1000000007
int map[500][500][2],v1[500],d[500][2];
void spfa(int s,int n)
{
int i,f=0,top=0,q[20000],num=MAX;
memset(v1,0,sizeof(v1));
for(i=0;n>i;i++)
{
d[i][0]=MAX;
d[i][1]=MAX;
}
v1[s]=1;
d[s][0]=0;
d[s][1]=0;
q[top]=s;
top++;
while(f<top)
{
v1[q[f]]=0;
for(i=0;n>i;i++)
{
if(d[i][0]>d[q[f]][0]+map[q[f]][i][0])
{
d[i][0]=d[q[f]][0]+map[q[f]][i][0];
d[i][1]=d[q[f]][1]+map[q[f]][i][1];
if(v1[i]==0)
{
v1[i]=1;
q[top]=i;
top++;
}
}
else if(d[i][0]==d[q[f]][0]+map[q[f]][i][0]&&d[i][1]>d[q[f]][1]+map[q[f]][i][1])
{
d[i][1]=d[q[f]][1]+map[q[f]][i][1];
if(v1[i]==0)
{
v1[i]=1;
q[top]=i;
top++;
}
}
}
f++;
}
}
int main()
{
int t,i,i1,i2,n,m,s,d1,u,v,w,z;
scanf("%d",&t);
for(i=1;t>=i;i++)
{
scanf("%d %d %d %d",&n,&m,&s,&d1);
for(i1=0;n>i1;i1++)
{
for(i2=0;n>i2;i2++)
{
if(i1==i2)
{
map[i1][i2][0]=0;
}
else
{
map[i1][i2][0]=MAX;
}
}
}
for(i1=1;m>=i1;i1++)
{
scanf("%d %d %d %d",&u,&v,&w,&z);
if(map[u][v][0]>w)
{
map[u][v][0]=w;
map[u][v][1]=z;
map[v][u][0]=w;
map[v][u][1]=z;
}
}
spfa(s,n);
printf("%d %d\n",d[d1][0],d[d1][1]);
}
return 0;
}

/***************************************************
Code Len: 2012B
Result: Accepted
Take time: 0ms
Take Memory: 316KB
Submit time: 2016-07-23 17:13:52
****************************************************/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: