题目链接
题目描述
某华大学小飞中奖了!!!奖品是一张免费飞机票,唯一遗憾的是,这张飞机票有限定区间,需要从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;
}