Layout Poj 3169 差分约束与SPFA

今天运气不错,连a两道,在此再记录一下。(要是是这学期中能够找到这么多时间来写它就好了啊……悔不当初)

此题大意是说找到一群牛之间的满足差分约束关系下的最大值,那么按小于的标准建边跑最短路得到的就是最长路。算法导论这一章中讲到的是求一个差分约束的可行性问题,所以会多加一个点并将它作为源点来跑单源最短路径。这里是找到某一点的,所以不需多加那一个顶点,直接来跑SPFA即可。判断存在负环类似Bellman-Ford,找到它其中是否有一个点入队列多于n次就好(保险起见取n+1,反正多一次复杂度只是损失常数2333).另外发现应该多用类与结构的构造函数,帮我节省了许多代码空间。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;

#define MAXN 1003
#define INF 0x3f3f3f3f
int n, ml, md;
typedef struct Edge {
	int nextNode;
	int weight;
	struct Edge (int v, int w) {nextNode = v;weight = w;}
}Edge;
typedef struct Vertex {
	int nodeName;
	int distance;
	struct Vertex (int x, int dis) { nodeName = x; distance = dis; }
}Vertex;
class RestraintGraph
{
public:
	void init(int size)
	{
		for (int i = 0; i < size ; i++)
			edges[i].clear();
		while (vertices.empty() == false)
			vertices.pop();
		memset(verticesInQueue, 0, sizeof(verticesInQueue));
		memset(verticesInQueueTimes, 0, sizeof(verticesInQueueTimes));
		vertex.clear();
		for (int i = 0; i < size ; i++)
			vertex.push_back(INF);
	}
	void input()
	{
		int cow1, cow2, dis;
		for (int i = 0; i < ml; i++) {
			scanf("%d %d %d", &cow1, &cow2, &dis);
			_addEdge(cow1-1, cow2-1, dis);
		}
		for (int i = 0; i < md; i++) {
			scanf("%d %d %d", &cow1, &cow2, &dis);
			_addEdge(cow2-1 , cow1-1 , -dis);
		}
		for (int i = 0; i < n - 1 ; i++) 
			_addEdge(i+1, i, 0);
	}
	void SPFA(int s)
	{
		Vertex ss = Vertex(s, 0);
		vertex[s] = 0;
		vertices.push(ss);
		verticesInQueue[s] = true;
		verticesInQueueTimes[s]++;
		bool canSolve = true;
		while (vertices.empty() == false&&canSolve) {
			Vertex u = vertices.front();
			vertices.pop();
			int uu = u.nodeName,vv;
			verticesInQueue[uu] = false;
			for (int i = 0; i < edges[uu].size(); i++) {
				vv = edges[uu][i].nextNode;
				if (vertex[vv] > vertex[uu] + edges[uu][i].weight) {
					vertex[vv] = vertex[uu] + edges[uu][i].weight;
					if (!_check(vv)) {
						vertices.push(Vertex(vv, 0));
						verticesInQueueTimes[vv]++;
						if (verticesInQueueTimes[vv] > n + 1)
							canSolve = false;
						_set(vv);
					}
				}
			}
		}
		if (canSolve)
			printf("%d\n", vertex[n - 1] == INF ? -2 : vertex[n - 1]);
		else
			printf("-1\n");
	}
private:
	vector<Edge > edges[MAXN];
	vector<int > vertex;
	queue<Vertex > vertices;
	bool verticesInQueue[MAXN];
	int verticesInQueueTimes[MAXN];
	void _addEdge(int u, int v, int w){	edges[u].push_back(Edge(v,w));}
	bool _check(int v) { return verticesInQueue[v]; }
	void _set(int v) { verticesInQueue[v] == true; }
};
int main()
{
	RestraintGraph rg;
	while (scanf("%d %d %d", &n, &ml, &md) != EOF) {
		rg.init(n);
		rg.input();
		rg.SPFA(0);
	}
	return 0;
}

不过说来我的代码还是长的离谱啊。相比大神们最多几十行,确实太复杂了(中间想多了,实际上不用把队列元素设为Vertex的),继续努力。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值