HDU-3790最短路径问题,第十遍终于过了~

最短路径问题

                                                                  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                                                                               
 ->  Link  <-

   这道题题意很简单,n个景点,m条路(双向),每条路有一个距离和花费,然后给定起点和终点,求起点到终点的最短距离及花费,如果最短路径有多条,输出花费最小的那条

   基于数据范围不大,除了弗洛伊德其他的最短路解法都是可以的,博主习惯用迪杰斯特拉,所以本文介绍dij的解法;

   思路;最短路的变形,以前都是直接求出起点到终点的最短路,而这里就是加上了一个花费问题,所以我们在用dij算法时注意如果路径相同的时候取花费小的即可,否则,只要路径小,两个变量都无条件变;

   坑点:样例水过,就是不知道跪在哪,看了讨论区才知道有重边的情况,所以在输入的时候需要注意如果两个点路径有多条相同的取花费小的,否则取路径最短的那条不用管花费;也就是说,不管在输入或者输出的时候都要以路径为前提,一定要的是最短的,如果最短的有多条再取花费小的;

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f;
const int N=1000+10;
struct node
{
    int p,d;
} a[N][N];输入的;
struct node1
{
    int d,p;
} v[N];起点到i点的最短路径及花费;
int vis[N];
int main()
{
    int n,m,xx,yy,i,j,d,p;
    while(~scanf("%d%d",&n,&m)&&n&&m)
    {
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
                a[i][j].d=a[i][j].p=(i==j?0:INF);
        memset(vis,0,sizeof(vis));
        for(i=1; i<=m; i++)
        {
            scanf("%d%d%d%d",&xx,&yy,&d,&p);
            if(d<a[xx][yy].d)//如果最短路只有一条,两个变量都无条件改变;
            {
                a[xx][yy].d=a[yy][xx].d=d;
                a[xx][yy].p=a[yy][xx].p=p;
            }
            else if(d==a[xx][yy].d)//有多条相同的时候才取花费最小的;
            {
                a[xx][yy].p=a[yy][xx].p=min(p,a[xx][yy].p);
            }
        }
        scanf("%d%d",&xx,&yy);
        for(i=1; i<=n; i++) v[i].d=v[i].p=i==xx?0:INF;
        for(i=1; i<=n; i++)
        {
            int x,mm=INF;
            for(j=1; j<=n; j++)
                if(!vis[j]&&v[j].d<=mm)
                    mm=v[x=j].d;
            vis[x]=1;
            for(j=1; j<=n; j++)
            {
                if(v[j].d>a[x][j].d+v[x].d)
                {
                    v[j].d=a[x][j].d+v[x].d;
                    v[j].p=a[x][j].p+v[x].p;
                }
                else if(v[j].d==a[x][j].d+v[x].d)//如果最短路径有多条,取花费最小的;
                    v[j].p=min(v[j].p,a[x][j].p+v[x].p);
            }

        }
        printf("%d %d\n",v[yy].d,v[yy].p);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值