简单图论农场派对
题目 2406:
信息学奥赛一本通T1497-农场派对
时间限制: 2s 内存限制: 192MB 提交: 40 解决: 13
题目描述
原题来自:USACO 2007 Feb. Silver
N(1≤N≤1000) 头牛要去参加一场在编号为 x(1≤x≤N) 的牛的农场举行的派对。有 M(1≤M≤100000) 条有向道路,每条路长 Ti(1≤Ti≤100);每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这 N 头牛的最短路径(一个来回)中最长的一条的长度。 特别提醒:可能有权值不同的重边。输入格式
第 1 行:3 个空格分开的整数 N,M,X;
第 2…M 行:3 个空格分开的整数 Ai,Bi,Ti ,表示有一条从 Ai 到 Bi 的路,长度为 Ti 。输出格式
一行一个数,表示最长最短路的长度。
样例输入
复制
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样例输出
复制
10
思路:
只需要考虑建立反向边图,将各点到x的最短路,转换为x点到各点的反向变图最短路。
#include<bits/stdc++.h> using namespace std; typedef pair<int, int>PII; const int N = 1010, M = 100010; int h1[N], h2[N], e1[M], e2[M], ne1[M], ne2[M], w1[M], w2[M], idx1, idx2; bool st1[N], st2[N]; int dis1[N], dis2[N]; int n, m, x; void add1(int a, int b, int c) { e1[idx1] = b, w1[idx1] = c, ne1[idx1] = h1[a], h1[a] = idx1++; } void add2(int a, int b, int c) { e2[idx2] = b, w2[idx2] = c, ne2[idx2] = h2[a], h2[a] = idx2++; } void dij(int x, int h[], bool st[], int dis[], int w[], int ne[], int idx,int e[]) { priority_queue<PII, vector<PII>, greater<PII>>q; q.push({ 0,x }); dis[x] = 0; while (q.size()) { auto t = q.top(); q.pop(); int v = t.second; if (st[v]) { continue; } st[v] = true; for (int i = h[v]; ~i; i = ne[i]) { int j = e[i]; if (st[j]) { continue; } if (dis[j] > dis[v] + w[i]) { dis[j] = dis[v] + w[i]; q.push({ dis[j],j }); } } } } void solve() { cin >> n >> m >> x; memset(h1, -1, sizeof h1); memset(h2, -1, sizeof h2); memset(dis1, 0x3f, sizeof dis1); memset(dis2, 0x3f, sizeof dis2); for (int i = 1; i <= m; i++) { int a, b, c; cin >> a >> b >> c; add1(a, b, c); add2(b, a, c); } dij(x, h1, st1, dis1, w1, ne1, idx1,e1); dij(x, h2, st2, dis2, w2, ne2, idx2,e2); int ans = 0; for (int i = 1; i <= n; i++) { ans = max(ans, dis1[i] + dis2[i]); } cout << ans; } int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int T; //cin >> T; solve(); return 0; }