您的位置:首页 > 其它

hdu 3790 最短路径问题(Dijkstra)

2016-01-11 12:46 471 查看

Problem Description

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

Input

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。

(1<n<=1000, 0<m<100000, s != t)

Output

输出 一行有两个数, 最短距离及其花费。

Sample Input

3 2
1 2 5 6
2 3 4 5
1 3
0 0


Sample Output

9 11

代码1:把图中的点分别设成1-n,dijkstra带beg(起始点参数)

#include <iostream>
#include <memory.h>
#include <stdio.h>
#define NUM 1005
#define INF 0x3f3f3f3f

using namespace std;

int n;
int cost[NUM];
int lowcost[NUM];
int g[NUM][NUM];
int gcost[NUM][NUM];
int vis[NUM];

void Dijkstra(int beg)
{
int k;
memset(vis,0,sizeof(vis));

for(int i=1; i<=n; i++)
{
lowcost[i]=g[beg][i];
cost[i]=gcost[beg][i];
}
vis[beg]=1;
for(int i=1; i<=n; i++)
{
int Min=INF;
for(int j=1; j<=n; j++)
{
if(lowcost[j]<Min&&!vis[j])
{
Min=lowcost[j];
k=j;
}
}
vis[k]=1;
for(int j=1; j<=n; j++)
{
if(lowcost[k]+g[k][j]<lowcost[j]&&!vis[j])
{
lowcost[j]=lowcost[k]+g[k][j];
cost[j]=cost[k]+gcost[k][j];
}
else if(lowcost[k]+g[k][j]==lowcost[j])
{
if(cost[k]+gcost[k][j]<cost[j])
{
//lowcost[j]=lowcost[k]+g[k][j];
cost[j]=cost[k]+gcost[k][j];
}
}

}
}
}
int main()
{
int a,b,d,p;
int m,s,e;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
g[i][j]=INF;
gcost[i][j]=INF;
}
}
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(d<g[a][b])
{
g[a][b]=g[b][a]=d;
gcost[a][b]=gcost[b][a]=p;
}
else if(d==g[a][b])
{
if(p<gcost[a][b])
gcost[a][b]=gcost[b][a]=p;
}
}
cin>>s>>e;
Dijkstra(s);
cout<<lowcost[e]<<" "<<cost[e]<<endl;
}
return 0;
}

代码2:把图中的点设置成0-n,在main函数中加入超级源点,起始点仍为0

<pre name="code" class="cpp">#include <iostream>
#include<cstring>
#include <stdio.h>

using namespace std;

#define INF 0x3f3f3f3f

int d[1002][1002],p[1002][1002],vis[1002],lowcost[1002],lowdis[1002];
int n,m,a,b,q,w,s,t;
void Dijkstra()
{
int k;
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++)
{
lowdis[i]=d[0][i];
lowcost[i]=p[0][i];
}
vis[0]=1;
for(int i=1;i<=n;i++)
{
//int k=1;
int Min=INF;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&lowdis[j]<Min)
{
k=j;
Min=lowdis[j];
}
}

vis[k]=1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&lowdis[k]+d[k][j]<lowdis[j]){
lowcost[j]=p[k][j]+lowcost[k];
lowdis[j]=d[k][j]+lowdis[k];
}
else if(!vis[j]&&lowdis[k]+d[k][j]==lowdis[j]&&lowcost[k]+p[k][j]<lowcost[j]){

lowcost[j]=p[k][j]+lowcost[k];
}

}
}
}

int main()
{
while(cin>>n>>m&&(n||m)){
for(int i=0;i<=n;i++){ //图中的点从0开始
for(int j=0;j<=n;j++){
d[i][j]=INF;
p[i][j]=INF;
}
}
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&a,&b,&q,&w);
if(d[a][b]>q)
{
d[a][b]=d[b][a]=q;
p[a][b]=p[b][a]=w;
}
else if(q==d[a][b])
{
if(w<p[a][b])
{
p[a][b]=p[b][a]=w;
}
}

}
scanf("%d%d",&s,&t);   //加入超级源点
d[0][s]=d[s][0]=0;
p[0][s]=p[s][0]=0;
Dijkstra();
cout<<lowdis[t]<<" "<<lowcost[t]<<endl;
}

return 0;
}

[code]本题目若用Floyd会超时,大概是因为我在细节没有优化,附上代码,请大家指出不足改进之处
#include <iostream>
#include <memory.h>
#include <stdio.h>
#define NUM 1001
#define INF 0x3f3f3f3f

using namespace std;

int n;
int lowcost[NUM][NUM];
int dis[NUM][NUM];
int path[NUM][NUM];
int g[NUM][NUM];

void Floyd()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=g[i][j];
path[i][j]=i;
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][j]>dis[i][k]+dis[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
lowcost[i][j]=lowcost[i][k]+lowcost[k][j];
path[i][j]=path[k][j];
}
else if(dis[i][j]==dis[i][k]+dis[k][j])
{
if(lowcost[i][j]>lowcost[i][k]+lowcost[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
lowcost[i][j]=lowcost[i][k]+lowcost[k][j];
path[i][j]=path[k][j];
}
}
}
}
}
}
int main()
{
int a,b,d,p;
int m,s,e;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
g[i][j]=INF;
lowcost[i][j]=INF;
}
g[i][i]=0;
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(d<g[a][b])
{
g[a][b]=d;
lowcost[a][b]=p;
}
else if(d==g[a][b])
{
if(p<lowcost[a][b])
lowcost[a][b]=p;
}
}
Floyd();
cin>>s>>e;
cout<<dis[s][e]<<" "<<lowcost[s][e]<<endl;
}
return 0;
}

[/code]


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: