最短路专题

http://poj.org/problem?id=1860
题意:某个地区有n种货币,m种货币交换方式,每种交换方式可以用 x货币交换y货币 或 y货币交换x货币 每种交换方式都有税率与手续费,如果用x换y,设税率ratexy,与手续费costxy, 那么会得到(x-costxy)*ratexy价值的y货币。 现在nike手上有s类的货币v元,问通过交换货币是否可以让他的货币价值增加(最终交换结束后手上的货币要求是s类的货币)。

思路:spfa返回1的条件是手上s类的货币大于v(即d[s]>v)。

#include <string>
#include <queue>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#include <set>
#include <map>
#pragma warning(disable:4996)
using namespace std;

typedef long long ll;
typedef long double ld;
const int maxn = 2e5 + 9, inf = 0x3f3f3f3f;

double dis[111][111], d[111], rate[111][111], cost[111][111];
bool vis[maxn];
int times[maxn], n, m, s;
double v;

bool spfa(int start){
	queue<int>q;
	for (int i = 0; i < 111; i++) {
		times[i] = vis[i] = d[i] = 0;
	}

	q.push(start);
	vis[start] = 1;
	d[start] = v;
	times[start] = 1;
	int u;
	while (!q.empty()) {
		u = q.front();
		q.pop();
		vis[u] = 0;
		for (int i = 1; i <= n; i++) {
			if ((d[u] - cost[u][i]) * rate[u][i] > d[i]) {
				d[i] = (d[u] - cost[u][i]) * rate[u][i];
				if (vis[i] == 0) {
					vis[i] = 1;
					q.push(i);
					times[i]++;
					if (d[start] > v) {//这里不能通过d[i]>=n来返回true,因为初始货币可能不在正环里面,因此wa了一发,难受。
						return true;
					}
				}
			}
		}
	}
	return false;
}

int main() {
	cin >> n >> m >> s >> v;
	for (int i = 0; i < m; i++) {
		int x, y;
		double rxy, ryx, cxy, cyx;
		cin >> x >> y >> rxy >> cxy >> ryx >> cyx;
		cost[x][y] = cxy;
		cost[y][x] = cyx;
		rate[x][y] = rxy;
		rate[y][x] = ryx;
	}
	if (spfa(s)) {
		cout << "YES" << endl;
	}
	else cout << "NO" << endl;
	return 0;
}

http://poj.org/problem?id=3159
题意:给出n个点,每个点都有一个值,再给出m组的关系:x,y,z
表示点y的值最多比点x的值要多z。问点1的值最多可以与点n差多少。
思路:对于题意可以给出两点之间的关系:d[y]-d[x]<=z;因为差值要最大,所以直接取z作为两个之间的差值。
那么对于m对关系,跑一边spfa+stack求最长路,或者dijstra+堆优化求最长路。

这题spfa不能配合queue,不然会超时。
ps:spfa+queue与spfa+stack的区别就和dfs和bfs的区别一样,stack取最后一个放进去的点,一条路走到黑。而queue取第一个放进去的点,一次走好几条路。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <stack>
 
using namespace std;
 
#define N 200000
#define INF 0x3f3f3f3f
#define met(a, b) memset (a, b, sizeof (a))
 
int vis[N], dist[N], head[N], cnt, n, m;
 
struct node
{
	int u, v, flow, next;
} edge[N*4];
 
void Init ()
{
	met (vis, 0);
	met (head, -1);
 
	for (int i=0; i<=n; i++)
        dist[i] = INF;
 
	cnt = 0;
}
 
void addedge (int u, int v, int flow)
{
	edge[cnt].u = u;
	edge[cnt].v = v;
	edge[cnt].flow = flow;
	edge[cnt].next = head[u];
	head[u] = cnt++;
}
 
void spfa ()
{
	stack <int> sta;
 
	while (!sta.empty()) sta.pop();
 
	sta.push (1);
	dist[1] = 0;
	vis[1] = 1;
 
	while (!sta.empty())
	{
		int u = sta.top(); sta.pop();
		vis[u] = 0;
 
		for (int i=head[u]; i!=-1; i=edge[i].next)
		{
			int v = edge[i].v;
			int flow = edge[i].flow;
 
			if (dist[v] > dist[u] + flow)
			{
				dist[v] = dist[u] + flow;
				if (!vis[v])
				{
					sta.push (v);
					vis[v] = 1;
				}
			}
		}
	}
	printf ("%d\n", dist[n]);
}
 
int main ()
{
	while (scanf ("%d %d", &n, &m) != EOF)
	{
	    Init();
		int u, v, flow;
		for (int i=1; i<=m; i++)
		{
			scanf ("%d %d %d", &u, &v, &flow);
			addedge (u, v, flow);
		}
		spfa ();
	}
	return 0;
}
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值