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;
}