hdu 3499 Flight(spfa+反向图)

7 篇文章 0 订阅

题目:hdu 3499 Flight

题意:给好多个城市的机票价格,旅行过程中可以把某张机票价格减半。求城市A到城市B的最小费用。

思路:求出A到每个城市的价格和B到每个城市的价格,遍历每条边求出最小价格。写完spfa就各种wa,找了一下午。开始我以为是无向图,就建了一个图。算B到每个城市价格的时候就错了,应该建反向图的。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <deque>
#include <set>
#include <string>
using namespace std;
#define For(i,a) for(i=0;i<a;i++)
#define Foru(i,a,b) for(i=a;i<=b;i++)
#define Ford(i,a,b) for(i=a;i>=b;i--)
#define clr(ar,vel) memset(ar,vel,sizeof(ar))
#define PB push_back
#define maxint 0x7fffffff
const long long maxll =1LL<<60;
typedef long long ll;
const int maxn = 100010;
struct edge{int to, dis;};
vector<edge> G[maxn], GB[maxn];
map<string, int> ma;
bool vis[maxn];
ll s_dis[maxn], t_dis[maxn];
int n, m, cnt;
int getNum(string s){
	if( !ma.count(s)) return ma[s] = cnt++;
	else return ma[s];
}
void spfa(int s, ll *dis, vector<edge> *G){
	memset(vis, 0, sizeof(vis));
	fill(dis, dis+n, maxll);
	deque<int> q;
	q.push_back(s);
	vis[s] = 1;
	dis[s] = 0;
	while(q.size()){
		int fn = q.front(); q.pop_front();
		vis[fn] = 0;
		for(int i = 0; i < G[fn].size(); i ++){
			int to = G[fn][i].to;
			int vel = G[fn][i].dis;
			if( dis[to] > dis[fn] + vel) {
				dis[to] = dis[fn] + vel;
				if( !vis[to]) {
					if( q.size() && dis[to] < dis[q.front()]) q.push_front(to);
					else q.push_back(to);
					vis[to] = 1;
				}
			}
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	string f, t;
	int dis, from, to;
	while(cin >> n >> m){
//		cout << maxint << ' ' << maxll << endl;
		for(int i = 0; i < n; i ++) {
			G[i].clear();
			GB[i].clear();
		}
		ma.clear();
		cnt = 0;
		while(m--){
			cin >> f >> t >> dis;
			from = getNum(f); to = getNum(t);
			G[from].push_back((edge){to, dis});
			GB[to].push_back((edge){from, dis});
		}
		cin >> f >> t;
		from = getNum(f); to = getNum(t);
		spfa(from, s_dis, G);
		spfa(to, t_dis, GB);
		ll ans = maxll;
		for(int i = 0; i < n; i ++){
			for(int j = 0; j < G[i].size(); j ++){
				int t = G[i][j].to;
				dis = G[i][j].dis;
				if( s_dis[i] < maxll && t_dis[t] < maxll ) ans = min(ans, s_dis[i] + t_dis[t] + dis/2);
			}
		}
		if( ans >= maxll ) ans = -1;
		cout << ans << endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值