题目描述
寒假到了, N N N头牛都要去参加一场在编号为 X ( 1 ≤ X ≤ N ) X(1≤X≤N) X(1≤X≤N)的牛的农场举行的派对 ( 1 ≤ N ≤ 1000 ) (1≤N≤1000) (1≤N≤1000),农场之间有 M ( 1 ≤ M ≤ 100000 ) M(1≤M≤100000) M(1≤M≤100000)条有向路,每条路长 T i ( 1 ≤ T i ≤ 100 ) Ti(1≤Ti≤100) Ti(1≤Ti≤100)。
每头牛参加完派对后都必须回家,无论是去参加派对还是回家,每头牛都会选择最短路径,求这 N N N头牛的最短路径(一个来回)中最长的一条路径长度。
输入输出格式
输入格式:
第一行三个整数 N , M , X N,M, X N,M,X;
第二行到第 M + 1 M+1 M+1行:每行有三个整数 A i , B i , T i A_i,B_i, T_i Ai,Bi,Ti ,表示有一条从 A i A_i Ai农场到 B i B_i Bi农场的道路,长度为 T i T_i Ti。
输出格式:
一个整数,表示最长的最短路得长度。
输入样例#1:
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
输出样例#1:
10
这个题是比较经典的图论模板题。题目中说牛去目的地和回家都会走最短路,所以我们只需要跑一边 1 − n 1 -n 1−n 和 n − 1 n-1 n−1 的最短路即可, n − 1 n-1 n−1的最短路我们可以建一边反向图来实现。
code
#include
using namespace std;
const int maxn = 2200;
struct node
{
int f, t, v;
}e[200005];
int dis[maxn][3], tot, n, m, xx , ans;
int x[200005], y[200005], nxt[200005], head[maxn], used[maxn] , z[200005];
inline void build(int a, int b, int c)
{
tot++;
e[tot].f = a; e[tot].t = b, e[tot].v = c;
nxt[tot] = head[a];
head[a] = tot;
}
queue<int>q;
inline void spfa(int s , int tim)
{
for (int i = 1; i <= n; i++) dis[i][tim] = 1e9;
dis[s][tim] = 0;
used[s] = 1;
q.push(s);
while (!q.empty())
{
int w = q.front();
q.pop();
used[w] = 0;
for (int i = head[w]; i; i = nxt[i])
{
int u = e[i].t;
if (dis[u][tim] > dis[w][tim] + e[i].v)
{
dis[u][tim] = dis[w][tim] + e[i].v;
if (!used[u])
{
used[u] = 1;
q.push(u);
}
}
}
}
}
inline void rebuild()
{
for (int i = 1; i <= n; i++) used[i] = 0;
for (int i = 1; i <= tot; i++)
{
e[i].f = 0;
e[i].t = 0;
e[i].v = 0;
}tot = 0;
memset(head, 0, sizeof(head));
memset(nxt, 0, sizeof(nxt));
for (int i = 1; i <= m; i++)
build(y[i], x[i], z[i]);
}
int main()
{
cin >> n >> m >> xx;
for (int i = 1; i <= m; i++)
{
cin >> x[i] >> y[i] >> z[i];
build(x[i], y[i] , z[i]);
}
spfa(xx, 1);
rebuild();
spfa(xx, 2);
for (int i = 1; i <= n; i++)
ans = max(ans, dis[i][1] + dis[i][2]);
printf("%d", ans);
//system("pause");
}
End