CUGB图论专场:B - ROADS(邻接表+dijkstra优先队列优化)

B – ROADS
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit 
Status

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

题意:求征税k内从1到n的最短路。

思路:这题我真不想说了,做了整整一天啦!我承认自己太笨了,只能默默努力了。WA了好多发,然后发现错误后,又T了好多发,改进了好多次,到最后用multimap才水过……唉……

第一种做法:multimap用时250ms

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define M 10010
#define INF 10000000
using namespace std;
typedef long long ll;
int k,n,r,MIN=INF;
multimap<int,int>z;
multimap<int,int>::iterator it;
struct abc
{
    int t,val,way;
    bool operator < (const struct abc a)const
    {
        if(val==a.val) return a.way<way;
        return a.val<val;
    }
};
struct ab
{
    int s,d,l,t;           //刚开始没有用这个结构体,用的是二维数组代替的,T了好多发才改成multiset了才加了这个结构体
}e[M];
void dijkstra()
{
    priority_queue<abc>q;    //优先队列节省点时间,因为每次出队都是从最小值开始的,所以比较快
    abc s1,s2,s3;
    s1.t=1; s1.val=0; s1.way=0;
    q.push(s1);
    while(!q.empty())
    {
        int n1,t1,val,i,way,num;
        s2=q.top(); q.pop();
        n1=s2.t; val=s2.val; way=s2.way;
        if(n1==n) {MIN=val;break;}    //因为是优先队列,所以只要到n就找到最小值了
        num=z.count(n1);
        it=z.find(n1);           //找到e[s].s在第几行,即地址,本来想用哈希思想做的,但是转来转去比较头晕,所以用了笨方法的STL
        for(i=0;i<num;i++,it++)
        {
            t1=(*it).second;         //取出e[s].
            if(way+e[t1].t<=k)
            {
                s3.t=e[t1].d; s3.val=val+e[t1].l;
                s3.way=way+e[t1].t;
                q.push(s3);
            }
        }
    }
    if(MIN==INF) printf("-1\n");
    else printf("%d\n",MIN);
}
int main()
{
    int s,d,l,t,i;
    scanf("%d%d%d",&k,&n,&r);
    for(i=0;i<r;i++)
    {
        scanf("%d%d%d%d",&e[i].s,&e[i].d,&e[i].l,&e[i].t);
        z.insert(pair<int,int>(e[i].s,i));
    }
    dijkstra();
    return 0;
}

第二种做法:邻接表,用时32ms

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define M 10010
#define INF 10000000
using namespace std;
typedef long long ll;
int n,m,i,u,v,w,d,c,cost,tot,ans=INF,head[M];
struct node
{
    int n,d,c;
    bool operator < (const struct node a)const
    {
        if(a.d == d) return a.c < c;
        return a.d < d;
    }
}s,x,y;
struct edge
{
    int u,v,w,c,next;
} e[M];
void dijkstra()
{
    priority_queue<node>q;
    s.n = 1; s.d = 0; s.c = 0;
    q.push(s);
    while(!q.empty())
    {
        x = q.top(); q.pop();
        u = x.n; d = x.d;
        if(u == n) {ans = x.d; break;}
        for(i=head[u]; i!=-1; i=e[i].next)
        {
            v = e[i].v; w = e[i].w; c = e[i].c;
            if(x.c + c <= cost) //在花费允许的范围内可以去到这个点
            {
                y.n = v; y.d = d + w; y.c = x.c + c;
                q.push(y);
            }
        }
    }
    if(ans==INF) printf("-1\n");
    else printf("%d\n",ans);
}
int main()
{
    scanf("%d%d%d",&cost,&n,&m);
    memset(head,-1,sizeof(head));
    tot = 0;
    for(i=0;i<m;i++)
    {
        scanf("%d%d%d%d",&u,&v,&w,&c);
        e[tot].u = u; e[tot].v = v;
        e[tot].w = w; e[tot].c = c;
        e[tot].next = head[u];     //邻接表
        head[u] = tot++;
    }
    dijkstra();
    return 0;
}

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/u011466175/article/details/18630013
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞