逛街 最短距离+花费

逛街

时间限制: 1 Sec 内存限制: 128 MB

题目描述

假设渣渣灰有一个女朋友,他的女朋友要他陪着一起去公园。由于渣渣灰不喜欢运动,所以他想找一条最短的路到达公园。由于途中会有许多消费点,而每到一个消费点女朋友就要购物,而渣渣灰比较抠,所以假如有多条最短路,则他会选择途中消费点最便宜的。给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s,终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

输入

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

输出

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

样例输入

2 2
1 2 5 10
2 1 4 12
1 2

4 4
1 2 5 6
2 3 4 5
1 4 5 10
4 3 4 2
1 3

6 7
1 2 5 6
1 3 5 1
2 6 2 1
3 4 1 1
4 2 1 1
4 5 1 1
5 2 3 1
5 6

0 0

样例输出

4 12
9 11
4 3

提示

输入样例的空行只是为了让大家分辨数据,输入有没有空行都没关系。输出样例没有空行。

题解

dijkstra算法求单源最短路简单扩展,我们再创建一个value数组储存花费情况。在松弛时对value进行改变。

松弛成功则value(s->i)=value(s->k->i)。

若最短路相等则对value值进行比较,即value(s->i)=min(value(s->k->i),value(s->i))。

s为源点,i为当前终点,k为中间点。最终输出最短路及对应value值即可。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e3+10;
int n,m;
struct node
{
    int ds,cs;
}road[maxn][maxn];
int dis[maxn];//最短距离
bool vis[maxn];
int cost[maxn];//花费
void dijkstra(int s)
{
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    memset(cost,inf,sizeof(cost));
    dis[s]=0;
    cost[s]=0;
    vis[s]=1;
    for(int i=1;i<=n;i++)
        dis[i]=road[s][i].ds;

    for(int i=1;i<=n;i++){
         cost[i]=road[s][i].cs;
         //printf("%d:%d\n",i,dis[i]);
    }

    for(int u=1;u<n;u++)
    {
        int minD=inf,k=-1;
        for(int i=1;i<=n;i++){
            if(!vis[i]&&dis[i]<minD)
            {
                k=i;
                minD=dis[i];
            }
        }
        vis[k]=1;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]&&dis[k]+road[k][i].ds<dis[i])
            {
                dis[i]=dis[k]+road[k][i].ds;
                cost[i]=cost[k]+road[k][i].cs;
            }//if

            if(!vis[i]&&dis[k]+road[k][i].ds==dis[i]
               &&cost[i]>cost[k]+road[k][i].cs)
            {
                cost[i]=cost[k]+road[k][i].cs;
            }//if

        }//for
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)&&n&&m){
        memset(road,inf,sizeof(road));
        for(int i=1;i<=m;i++){
        int a,b,d,p;
        scanf("%d%d%d%d",&a,&b,&d,&p);
        if(d<=road[a][b].ds)//处理路径距离
        {
            if(d==road[a][b].ds)//如果距离相等,存放最短的花费
            road[a][b].cs=road[b][a].cs=min(p,road[a][b].cs);
            else //存放新路径的费用
            road[a][b].cs=road[b][a].cs=p;
            road[a][b].ds=road[b][a].ds=d;//填充路径
        }
    }
        int s,t;
        scanf("%d%d",&s,&t);
        dijkstra(s);
        printf("%d %d\n",dis[t],cost[t]);
    }
    return 0;
}
#include <stdio.h>
#include <string.h>
#define INF 0x3f3f3f3f
#define Min(a,b) a>b?b:a
struct Node
{
	int adj,val;
}g[1005][1005];
int dist[1005];//距离
int value[1005];//费用
int used[1005];//标记
int n,m,i,j;
void Dijkstra(int s)
{
	memset(dist,0x3f,sizeof(dist));
	memset(value,0x3f,sizeof(value));
	memset(used,0,sizeof(used));
	dist[s]=0;//从起点开始
	value[s]=0;
	while(1)
	{
		int k,u=-1,d[1005];
		int min=INF;
		memset(d,0,sizeof(d));
		for(i=1;i<=n;i++)
			if(used[i]==0&&dist[i]<min)//找出从起点到下一个最小距离的顶点
			{
				min=dist[i];//记录最小值
				u=i;//记录下标
			}
		if(u==-1)//判断所有顶点是否都到达过
			return ;
		for(i=1,k=0;i<=n;i++)
			if(dist[u]==dist[i]&&used[i]==0)
				d[k++]=i;//从起点到下一个要访问的顶点的最小距离可能有多个
		for(i=0;i<k;i++)
			used[d[i]]=1;
		for(i=0;i<k;i++)//多个满足的点分别进行迪杰斯特拉最短路查找
			for(j=1;j<=n;j++)
				if(g[d[i]][j].adj!=INF && (dist[d[i]]+g[d[i]][j].adj)<=dist[j])
				{//原理与 main()函数中建立邻接矩阵一样
					if((dist[d[i]]+g[d[i]][j].adj)<dist[j])//小于的情况
						value[j]=value[d[i]]+g[d[i]][j].val;
					else
						value[j]=Min(value[j],value[d[i]]+g[d[i]][j].val);
					dist[j]=dist[d[i]]+g[d[i]][j].adj;
				}
	}
}
int main()
{
	while(scanf("%d%d",&n,&m) && (n||m))
	{
		int a,b,d,p;
		memset(g,0x3f,sizeof(g));
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d%d",&a,&b,&d,&p);
			if(d<=g[a][b].adj)//处理路径距离问题
			{
				if(d==g[a][b].adj)//如果距离相等,则存放最少的费用
					g[a][b].val=g[b][a].val=Min(p,g[a][b].val);
				else//否则,存放新路径距离的费用
					g[a][b].val=g[b][a].val=p;
				g[a][b].adj=g[b][a].adj=d;//填充路径距离
			}
		}
		int s,t;
		scanf("%d%d",&s,&t);
		Dijkstra(s);
		printf("%d %d\n",dist[t],value[t]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81234791