免费机票【SPFA】【南华大学第十五届ACM程序设计竞赛】

题目链接


题目描述

        某华大学小飞中奖了!!!奖品是一张免费飞机票,唯一遗憾的是,这张飞机票有限定区间,需要从k个区间中选择其一。小飞打算高高兴兴的出去玩啦,但是,从s地出发,去往e地,可能没有直达的飞机票,可能需要转机(所有飞机线路都是无向的),小飞毕竟是个学生党,出去玩首先得考虑省钱,所以,小飞遇到麻烦了,请帮小飞计算最便宜的一条路线,小飞会很感激你的。

输入描述:

第一行为三个整数n,s,e,n表示n个不同城市的飞机场,s为出发点,e为目的地。(1<=n<=1000,  1<=s,e<=n)

第二行为一个整数m,表示m条普通飞机线路,接下来的m行描述每条线路,每行包含三个整数a、b、c,a、b代表普通飞机线路两端,c表示价格。(1<=m<=1000,  1<=a,b<=n,  1<=c<=1000)

接下来的一行为一个整数k,表示k个免费机票的航线区间, 然后k行来描述每条免费航线,每行两个整数a’、b’,    分别代表免费航线两端。(1<=k<=1000,  1<=a’,b’<=n)

输出描述:

每个测试数据有两行输出,第一行为是否使用免费飞机票,是则输出“Yes”,否则输出“No”。第二行输出总共花费。

  我们就是要找出所有的K个免费端点(u -> v)两端的从S出发和从T出发做到达的距离加上这段免费距离,去看是否需要使用这段中间的免费区间。具体可以看看代码,很好理解的。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e3 + 7, maxE  =4e3 + 7;
int N, S, T, dis[2][maxN], res, M, head[maxN], cnt, K, ans;
struct Eddge
{
    int nex, to, cost;
    Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), cost(c) {}
}edge[maxE];
inline void addEddge(int u, int v, int cost)
{
    edge[cnt] = Eddge(head[u], v, cost);
    head[u] = cnt++;
}
inline void _add(int u, int v, int cost) { addEddge(u, v, cost); addEddge(v, u, cost); }
bool inque[maxN];
queue<int> Q;
inline void spfa(int st, int op)
{
    memset(inque, false, sizeof(inque));
    while(!Q.empty()) Q.pop();
    Q.push(st); inque[st] = true;   dis[op][st] = 0;
    while(!Q.empty())
    {
        int u = Q.front();  Q.pop();    inque[u] = false;
        for(int i=head[u], v, c; ~i; i=edge[i].nex)
        {
            v = edge[i].to; c = edge[i].cost;
            if(dis[op][v] > dis[op][u] + c)
            {
                dis[op][v] = dis[op][u] + c;
                if(!inque[v])
                {
                    inque[v] = true;
                    Q.push(v);
                }
            }
        }
    }
}
inline void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(dis, INF, sizeof(dis));
}
int main()
{
    while(scanf("%d%d%d", &N, &S, &T)!=EOF)
    {
        init();
        scanf("%d", &M);
        for(int i=1, u, v, w; i<=M; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            _add(u, v, w);
        }
        spfa(S, 0);
        spfa(T, 1);
        scanf("%d", &K);
        ans = dis[0][T];
        bool flag = false;
        for(int i=1, u, v; i<=K; i++)
        {
            scanf("%d%d", &u, &v);
            if(ans > dis[0][u] + dis[1][v])
            {
                flag = true;
                ans = dis[0][u] + dis[1][v];
            }
            if(ans > dis[1][u] + dis[0][v])
            {
                flag = true;
                ans = dis[1][u] + dis[0][v];
            }
        }
        printf(flag ? "Yes\n" : "No\n");
        printf("%d\n", ans);
    }
    return 0;
}

 

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值