POJ 3268 - Silver Cow Party(链式前向星正反建图 + 两次最短路spfa)

来自 N (1 ≤ N ≤ 1000)个农场的奶牛的编号分别为1,2, … ,N。现在在农场 X (1 ≤ X ≤ N) 举行聚会。总共有 M (1 ≤ M ≤ 100,000) 条单向通道。路 i 需要时间 Ti 才能通过。每头牛都需要参加聚会并返回,而且它们均选择花费时间最短的路线。
问:在所有的奶牛中,所花费的最长时间为多少?
Input
第一行包含三个整数N,M,X。
在接下来的M行中,每行都包括三个整数A,B和T,表示从农场A到B需要花费时间T。

Output

输出奶牛所花的最大时间。

Sample Input

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

Sample Output

10

题目大意:

给出 n 个点,m 条边,和一个点 x ,接下来有 m 行 a b c ,表示a b 两点之间有一条权值为 c 的单向边,奶牛们要去 x 点聚会,每一头牛都走最短路,询问哪一头奶牛往返时间最长,输出这个最长时间。

解题思路:

正反双向建图,建两个图,跑两遍spfa即可。

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define lowbit(x) x & (-x)

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 50;
const int M = 1e5 + 50;

int h[N], ne[M], w[M], e[M], idx;
int h1[N], ne1[M], w1[M], e1[M], idx1;
int n, m, x;
int dis[N], dis1[N];
int vis[N], vis1[N];

void add(int a, int b, int c)//链式前向星正反建两个图
{
	e[idx] = b;
	w[idx] = c;
	ne[idx] = h[a];
	h[a] = idx++;

	e1[idx1] = a;
	w1[idx1] = c;
	ne1[idx1] = h1[b];
	h1[b] = idx1++;
}

void spfa()//正着跑一遍spfa
{
	memset(dis, 0x3f, sizeof dis);
	dis[x] = 0;

	queue<int > q;
	q.push(x);
	vis[x] = true;

	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		vis[t] = false;

		for (int i = h[t]; ~i; i = ne[i])
		{
			int j = e[i];
			if (dis[t] + w[i] < dis[j])
			{
				dis[j] = dis[t] + w[i];
				if (!vis[j])
				{
					vis[j] = true;
					q.push(j);
				}
			}
		}
	}
}

void respfa()//反向再跑一遍
{
	memset(dis1, 0x3f, sizeof dis1);
	dis1[x] = 0;

	queue<int > q;
	q.push(x);
	vis1[x] = true;

	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		vis1[t] = false;

		for (int i = h1[t]; ~i; i = ne1[i])
		{
			int j = e1[i];
			if (dis1[t] + w1[i] < dis1[j])
			{
				dis1[j] = dis1[t] + w1[i];
				if (!vis1[j])
				{
					vis1[j] = true;
					q.push(j);
				}
			}
		}
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &x);

	memset(h, -1, sizeof h);
	memset(h1, -1, sizeof h1);

	while (m--)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c);
	}

	spfa();
	respfa();

	int ans = -1;

	for (int i = 1; i <= n; i ++)
		if (dis[i] != inf && dis1[i] != inf)
			ans = max(ans, dis[i] + dis1[i]);//ans取最大值,输出即可

	printf("%d\n", ans);

	return 0;
}
posted @ 2020-09-13 17:09  Hayasaka  阅读(74)  评论(0编辑  收藏  举报