POJ - 1724【有限制条件的最短路】+HDU- 3790【双重权值的最短路】

题目链接:http://poj.org/problem?id=1724


题目大意:给定最大费用K(走这些路所能用的最大钱数),点的个数N,边的条数R; 接着R行表示S,D,L,T表示从S到D的路的长度为L,花费为T; 求从1~N的最短路的长度。


分析:类似于最短路,多了一个限制条件,这时我们可以用优先队列来存,用spfa求最短路。让距离小的优先,距离相同的 时候让花费小的优先,判断当前点是否能到达下一点,如果能到,放入队列,直到找到目的地时跳出。如果不能到达,返回-1。


感想:其实思想还是差不多,在最短路的基础上加了一个限制条件做了一个变形,还是要深入理解最短路,用的还挺多的,记得比赛的时候我们刚开始想的也是最短路,不知道怎么去加那个限制条件,想想又觉得是网络流,网络流学的也不好,敲完模板不知道怎么去改,还是自己学的东西太少,要好好下功夫了。

比赛链接:https://cn.vjudge.net/contest/158506#overview

Code:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
const int maxn=105;
int tot,n,maxx;
struct node
{
    int y,di,fee;
    node(int yy=0,int dii=0,int fe=0)
    {
        y=yy,di=dii,fee=fe;
    }
    friend bool operator < (node a,node b)
    {
        if(a.di==b.di)
            return a.fee>b.fee;//花费
        else
            return a.di>b.di;//距离
    }
} eg[maxn];
vector<node>G[maxn];
priority_queue<node>q;
int spfa()
{
    while(!q.empty())
       q.pop();
    q.push(node(1,0,0));
    while(!q.empty())
    {
        node xx=q.top();
        q.pop();
        if(xx.y==n)//到达目的地直接跳出,返回最小花费
            return xx.di;
        for(int i=0; i<G[xx.y].size(); i++)
        {
            if(xx.fee+G[xx.y][i].fee<=maxx)//如果剩下的钱还够走到下一条路,继续走,直到到达目的地
            {
                q.push(node(G[xx.y][i].y,xx.di+G[xx.y][i].di,xx.fee+G[xx.y][i].fee));
            }
        }
    }
    return -1;
}
int main()
{
    int k,r;
    while(~scanf("%d%d%d",&maxx,&n,&r))
    {
        for(int i=0;i<=n;i++)
            G[i].clear();
        int a,b,c,d;
        for(int i=0; i<r; i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            G[a].push_back(node(b,c,d));
        }
        printf("%d\n",spfa());
    }
    return 0;
}

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790


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


分析:本题是双重权值的最短路径问题,做法跟一般的最短路差不多。

            要注意最短路长度相同的情况下最小花费的更新。

Code:

#define INF 0x3f3f3f3f
const int maxn=1005;
int vis[maxn],dis[maxn],cost[maxn];
int mp1[maxn][maxn],mp2[maxn][maxn];
int n,m;
void dij(int s,int t)
{
    for(int i=1; i<=n; i++)
    {
        dis[i]=mp1[s][i];
        cost[i]=mp2[s][i];
    }
    dis[s]=0,cost[s]=0;
    vis[s]=1;
    for(int i=2; i<=n; i++)
    {
        int minn=INF,pos=0;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&minn>dis[j])
            {
                minn=dis[j];
                pos=j;
            }
        }
       // cout<<minn<<"* ";
        vis[pos]=1;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j])
            {
                if(dis[j]>dis[pos]+mp1[pos][j])
                {
                    dis[j]=dis[pos]+mp1[pos][j];
                    cost[j]=cost[pos]+mp2[pos][j];
                }
                else if(dis[j]==dis[pos]+mp1[pos][j]&&cost[j]>cost[pos]+mp2[pos][j])//注意
                {
                    cost[j]=cost[pos]+mp2[pos][j];
                }
            }
        }
    }
    if(dis[t]==INF)
        printf("0 0\n");
    else
        printf("%d %d\n",dis[t],cost[t]);
}
void init()//初始化
{
    memset(vis,0,sizeof(vis));
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j)
            {
                mp1[i][j]=0;
                mp2[i][j]=0;
            }
            else
            {
                mp1[i][j]=INF;
                mp2[i][j]=INF;
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
            break;
        int a,b,d,p,x,y;
        init();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d%d",&a,&b,&d,&p);
            if(mp1[a][b]>d||(mp1[a][b]==d&&mp2[a][b]>p))
            {
                mp1[a][b]=mp1[b][a]=d;//长度
                mp2[a][b]=mp2[b][a]=p;//花费
            }
        }
        scanf("%d%d",&x,&y);
        dij(x,y);
    }
    return 0;
}



POJ - 1724 ROADS
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 15143 Accepted: 5470

Description

N cities named with numbers 1 ... N are connected with one-way roads. Each road has two parameters associated with it : the road length and the toll that needs to be paid for the road (expressed in the number of coins).
Bob and Alice used to live in the city 1. After noticing that Alice was cheating in the card game they liked to play, Bob broke up with her and decided to move away - to the city N. He wants to get there as quickly as possible, but he is short on cash.

We want to help Bob to find the shortest path from the city 1 to the city N that he can afford with the amount of money he has.

Input

The first line of the input contains the integer K, 0 <= K <= 10000, maximum number of coins that Bob can spend on his way.
The second line contains the integer N, 2 <= N <= 100, the total number of cities.

The third line contains the integer R, 1 <= R <= 10000, the total number of roads.

Each of the following R lines describes one road by specifying integers S, D, L and T separated by single blank characters :
  • S is the source city, 1 <= S <= N
  • D is the destination city, 1 <= D <= N
  • L is the road length, 1 <= L <= 100
  • T is the toll (expressed in the number of coins), 0 <= T <=100

Notice that different roads may have the same source and destination cities.

Output

The first and the only line of the output should contain the total length of the shortest path from the city 1 to the city N whose total toll is less than or equal K coins.
If such path does not exist, only number -1 should be written to the output.

Sample Input

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

Sample Output

11

Source

HDU 3790 最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 26110    Accepted Submission(s): 7781


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
 

Source

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值