有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
输出样例:
3 40
bellman-ford
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
int inf=0x3f3f3f3f;
int n,m,s,d,a[1000005][5],m1=inf,m2=inf;
int main()
{
int i,j,s,c,t,x,y,z,d1[505],d2[505];
scanf("%d %d %d %d",&n,&m,&s,&d);
for(i=1;i<=m;i++){
scanf("%d %d %d %d",&a[i][1],&a[i][2],&a[i][3],&a[i][4]);
a[i+m][1]=a[i][2];//
a[i+m][2]=a[i][1];//
a[i+m][3]=a[i][3];//由于是无向图,要加上这个
a[i+m][4]=a[i][4];//
}
memset(d1,inf,sizeof(d1));
memset(d2,inf,sizeof(d2));
d1[s]=d2[s]=0;
for(j=1;j<n;j++){//因为除起点外有n-1个点,所以n-1次循环起点足够到达每一个点
int flag=0;
for(i=1;i<=m*2;i++){
if(d1[a[i][2]]>d1[a[i][1]]+a[i][3]){
d1[a[i][2]]=d1[a[i][1]]+a[i][3];
d2[a[i][2]]=d2[a[i][1]]+a[i][4];
flag=1;
}
else if(d1[a[i][2]]==d1[a[i][1]]+a[i][3]&&d2[a[i][2]]>d2[a[i][1]]+a[i][4]){
// d1[a[i][2]]=d1[a[i][1]]+a1[i][3];
d2[a[i][2]]=d2[a[i][1]]+a[i][4];
flag=1;
}
}
if(!flag) break;
}
printf("%d %d",d1[d],d2[d]);
return 0;
}
dijskra (c)
迪杰斯特拉算法过程:
1.数组d中存放源点到其他点的最短距离,每次从数组d中选一个值最小且没有被访问过的点;
2.如果经过此点到其他点距离更短,则更新数组d;
3.标记此点已访问过,遍历其他点,直到所有点被访问完。
#include<stdio.h>
#define maxn 1005
int main()
{
int i,j,n,m,x,y,l,c,v,s,d,a[505][505][3],f[maxn]={0},b[maxn],p[maxn];
scanf("%d %d %d %d",&n,&m,&s,&d);
for(i=0;i<n;i++)
for(j=0;j<n;j++){
// a[i][j][0]=a[j][i][0]=maxn; a[i][j][1]=a[j][i][1]=maxn;
a[i][j][0]=maxn;a[i][j][1]=maxn;
}
while(m--){
scanf("%d %d %d %d",&x,&y,&l,&c);
a[x][y][0]=a[y][x][0]=l;
a[x][y][1]=a[y][x][1]=c;
}
for(i=0;i<n;i++){
b[i]=a[s][i][0];
p[i]=a[s][i][1];
}
// f[s]=1;
b[s]=0;
p[s]=0;
b[n]=maxn;
while(1){
v=n;
for(i=0;i<n;i++){
if(!f[i]&&b[i]<b[v])
v=i;
}
if(v==n) break;
f[v]=1;
for(i=0;i<n;i++){
if(!f[i]&&a[v][i][0]<maxn){
if(b[v]+a[v][i][0]<b[i]){
b[i]=b[v]+a[v][i][0];
p[i]=p[v]+a[v][i][1];
}
else if( b[v]+a[v][i][0]==b[i]&&p[v]+a[v][i][1]<p[i]){
// b[i]=b[v]+a[v][i][0];
p[i]=p[v]+a[v][i][1];
}
}
}
}
printf("%d %d",b[d],p[d]);
return 0;
}
dijskra (c++)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int N=505;
const int inf=0x3f3f3f3f;
typedef long long ll;
int n,m,st,ed;
int a[N][N][2];
int vis[N],d1[N],d2[N];
void spfa(){
memset(d1,inf,sizeof(d1));
memset(d2,inf,sizeof(d2));
d1[st]=d2[st]=0;
priority_queue<pair<int,int> >q;
q.push(make_pair(0,st));
while(!q.empty()){
int t=q.top().second;
q.pop();
if(vis[t]) continue;
vis[t]=1;
for(int i=1;i<=n;i++){
if(a[t][i][0]!=0){
if(d1[i]>d1[t]+a[t][i][0]){
d1[i]=d1[t]+a[t][i][0];
d2[i]=d2[t]+a[t][i][1];
if(!vis[i])
q.push(make_pair(-d1[i],i));
}
else if(d1[i]==d1[t]+a[t][i][0]&&d2[i]>d2[t]+a[t][i][1]){
d2[i]=d2[t]+a[t][i][1];
if(!vis[i])
q.push(make_pair(-d1[i],i));
}
}
}
}
}
int main()
{
int i,j,k,x,y,len,value;
scanf("%d %d %d %d",&n,&m,&st,&ed);
for(i=0;i<m;i++){
scanf("%d %d %d %d",&x,&y,&len,&value);
a[x][y][0]=a[y][x][0]=len;
a[x][y][1]=a[y][x][1]=value;
}
spfa();
printf("%d %d",d1[ed],d2[ed]);
return 0;
}
卑微dfs
最后一个点超时
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
int inf=0x3f3f3f3f;
int n,m,s,d,a[505][505],b[505][505],m1=inf,m2=inf;
int v[505];
void dfs(int start,int sum1,int sum2){
if(start==d){
if(sum1<m1){
m1=sum1;
m2=sum2;
}
else if(sum1==m1&&sum2<m2){
m1=sum1;
m2=sum2;
}
return;
}
v[start]=1;
for(int i=0;i<n;i++){
if(!v[i]&&a[start][i]&&sum1+a[start][i]<=m1){
dfs(i,sum1+a[start][i],sum2+b[start][i]);
}
}
v[start]=0;
}
int main()
{
int i,j,s,c,t,x,y,z;
scanf("%d %d %d %d",&n,&m,&s,&d);
while(m--){
scanf("%d %d %d %d",&x,&y,&z,&t);
a[x][y]=a[y][x]=z;
b[x][y]=b[y][x]=t;
}
dfs(s,0,0);
printf("%d %d",m1,m2);
return 0;
}