poj3268(最短路,dijkstra)

这篇博客介绍了如何利用Dijkstra算法解决图论问题,特别是找到图中一点到其他所有点的最短路径,以及通过反转边来找到回溯原点的最长距离。博主分享了C++实现的代码,并指出即使简单的Dijkstra算法也能通过题目测试,同时提到了图论中常见的拆点、加点和加边技巧。
/*
translation:
	给出一张图,给出图中的一个点。求图中其它点到该点并回到原点的最长距离是多少?
solution:
	dijkstra算法
	首先可以很容易求出从x到其它点的最小距离。然后求其它点到x的最小距离可以将图中所有的边反向
	然后求x到其它点的最小距离。如此只需要求两次即可。
note:
	1:本来以为无脑的对每一个点dijkstra会超时,没想到无脑的暴力dijkstra依然能过。但是明显这种方法更好。
	*拆点,加点,加边,加反向边这几种技巧是图论中经常见到的
date:
	2016.10.18
*/
#include <iostream>
#include <cstdio>
#include <utility>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;
const int maxn = 1000 + 5;
const int INF = 1e8;

struct Edge
{
	int to, cost;
	Edge(int to_ = 0, int cost_ = 0):to(to_),cost(cost_){}
};
typedef pair<int, int> P;

int n, m, x;
vector<Edge> G[maxn];
vector<Edge> rG[maxn];
int d[maxn],rd[maxn];

void dijkstra(int s)
{
	priority_queue<P, vector<P>, greater<P> > pq;
	fill(d, d+n+1, INF);
	d[s] = 0;
	pq.push(P(0, s));

	while(!pq.empty())
	{
		P p = pq.top();	pq.pop();
		int v = p.second;
		if(d[v] < p.first)	continue;
		for(int i = 0; i < G[v].size(); i++)
		{
			Edge e = G[v][i];
			if(d[e.to] > d[v] + e.cost)
			{
				d[e.to] = d[v] + e.cost;
				pq.push(P(d[e.to], e.to));
			}
		}
	}
}

void reDijkstra(int s)
{
	priority_queue<P, vector<P>, greater<P> > pq;
	fill(rd, rd+n+1, INF);
	rd[s] = 0;
	pq.push(P(0, s));

	while(!pq.empty())
	{
		P p = pq.top();	pq.pop();
		int v = p.second;
		if(rd[v] < p.first)	continue;
		for(int i = 0; i < rG[v].size(); i++)
		{
			Edge e = rG[v][i];
			if(rd[e.to] > rd[v] + e.cost)
			{
				rd[e.to] = rd[v] + e.cost;
				pq.push(P(rd[e.to], e.to));
			}
		}
	}
}

int main()
{
	//freopen("in.txt", "r", stdin);
	while(~scanf("%d%d%d", &n, &m, &x))
	{
		for(int i = 0; i <= n; i++)
		{
			G[i].clear();
			rG[i].clear();
		}

		int s, t, c;
		for(int i = 0; i < m; i++)
		{
			scanf("%d%d%d", &s, &t, &c);

			G[s].push_back(Edge(t, c));
			rG[t].push_back(Edge(s, c));
		}

		dijkstra(x);
		reDijkstra(x);

		int ans = -1;
		for(int i = 1; i <= n; i++)
		{
			if(i != x)	ans = max(ans, d[i] + rd[i]);
		}
		printf("%d\n", ans);
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值