POJ3268 Silver Cow Party 最短路

       题目大意是N个农场上的每一头牛都要去农场X参加聚会而且还要返回(返回路径不一定和来时的路径相同),给出一些农场间的路径和需要时间(路径是单向的),每头牛都会选择时间最少的路去农场X以及返回到自己的农场。计算出N头牛中需要花最长时间到达农场X的时间数。

       这题如果选用Floyd和Bellman算法的话因为复杂度过高(O(n ^ 3))而会超时,所以用dijkstra或者spfa才能够AC。因为路径是单向的,所以求出X到其他所有点最短路径后再将原有路径转置一下再计算一次X到其他所有点的最短路就可以了。

#ifndef HEAD
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map>

using namespace std;
#endif // !HEAD

#ifndef QUADMEMSET
inline void QuadMemSet(void* dst, int iSize, int value)
{
	iSize = iSize / 4;
	int* newDst = (int*)dst;
#ifdef WIN32
	__asm
	{
		mov edi, dst
			mov ecx, iSize
			mov eax, value
			rep stosd
	}
#else
	for (int i = 0; i < iSize; i++)
	{
		newDst[i] = value;

	}
#endif
}
#endif

struct PEge
{
	int from;
	int to;
	int cost;
	PEge* next;
};

struct PNode
{
	int to;
	int cost;
	bool operator()(const PNode& a1, const PNode& a2)
	{
		return a1.cost > a2.cost;
	}
};

PEge peges[100001];
int DD[1001];
PEge* pHead[1001];
PEge invpeges[100001];
PEge* invpHead[1001];

void Dijs(int s, PEge* pHead[])
{
	QuadMemSet(DD, sizeof(DD), 10000000);
	priority_queue<PNode, vector<PNode>, PNode> nodes;
	DD[s] = 0;
	int cur = s;
	int minnode = -1;
	int minpath = 1000000;
	int visited[1001] = { 0 };

	for (PEge* ege = pHead[s]; ege; ege = ege->next)
	{
		PNode node;
		node.to = ege->to;
		node.cost = ege->cost;
		nodes.push(node);
	}
	while (nodes.size() > 0)
	{
		if (visited[nodes.top().to])
		{
			nodes.pop();
		}
		else
		{
			int from = nodes.top().to;
			visited[from] = 1;
			DD[from] = nodes.top().cost;
			nodes.pop();
			for (PEge* ege = pHead[from]; ege; ege = ege->next)
			{
				if (visited[ege->to] == 0)
				{
					PNode node;
					node.to = ege->to;
					node.cost = min(DD[node.to], DD[from] + ege->cost);
					nodes.push(node);
				}
			}
		}
	}
}

int main()
{
#ifdef _DEBUG
	freopen("e:\\in.txt", "r", stdin);
#endif
	int N, M, X;
	scanf("%d %d %d\n", &N, &M, &X);

	memset(pHead, 0, sizeof(pHead));
	memset(invpHead, 0, sizeof(invpHead));
	for (int i = 0; i < M;i++)
	{
		int a, b, c;
		scanf("%d %d %d\n", &a, &b, &c);
		peges[i].from = a;
		peges[i].to = b;
		peges[i].next = pHead[a];
		peges[i].cost = c;
		pHead[a] = &peges[i];

		invpeges[i].from = b;
		invpeges[i].to = a;
		invpeges[i].next = invpHead[b];
		invpeges[i].cost = c;
		invpHead[b] = &invpeges[i];

	}
	int tmp[1001] = { 0 };
	
	int maxvalue = -1;
	Dijs(X, pHead);
	for (int i = 1; i <= N;i++)
	{
		tmp[i] += DD[i];
		if (maxvalue < tmp[i])
		{
			maxvalue = tmp[i];
		}
	}
	
	Dijs(X, invpHead);
	for (int i = 1; i <= N; i++)
	{
		tmp[i] += DD[i];
		if (maxvalue < tmp[i])
		{
			maxvalue = tmp[i];
		}
	}
	printf("%d\n", maxvalue);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值