[P1821 USACO07FEB] Cow Party S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
每次都求一遍从 u u u到 r r r的最短路时间开销很大。可以考虑建反图,从 r r r点开始进行最短路,这样就可以经过一次就得到所有的从 u u u到 r r r的最短路,之后再计算从 r r r到 u u u的最短路,两者相加就是一个来回。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 21;
int e[N], ne[N], h[N], idx,dis1[N],dis2[N],w[N],vis[N];
void add(int u,int v, int x) {
e[idx] = v, ne[idx] = h[u], w[idx] = x, h[u] = idx++;
}
int e2[N], ne2[N], h2[N], idx2,w2[N];
void add2(int u, int v, int x) {
e2[idx2] = v, ne2[idx2] = h2[u], w2[idx2] = x, h2[u] = idx2++;
}
int main()
{
int n,m,r; cin>>n>>m>>r;
memset(h, -1, sizeof(h));
memset(h2, -1, sizeof(h2));
for(int i = 0; i < m; ++i) {
int u,v,x; cin>>u>>v>>x;
add(u,v,x);
add2(v,u,x);
}
memset(dis1, 0x3f, sizeof(dis1));
memset(dis2, 0x3f, sizeof(dis2));
dis1[r] = 0;
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
q.push({0,r});
while(q.size()) {
auto tmp = q.top(); q.pop();
int u = tmp.second, d = tmp.first;
if(vis[u]) continue;
vis[u] = 1;
for(int i = h[u]; ~i; i = ne[i]) {
int v = e[i], x = w[i];
if(dis1[v] > d + x) {
dis1[v] = d + x;
q.push({dis1[v],v});
}
}
}
memset(vis, 0, sizeof(vis));
dis2[r] = 0;
q.push({0,r});
while(q.size()) {
auto tmp = q.top(); q.pop();
int u = tmp.second, d = tmp.first;
if(vis[u]) continue;
vis[u] = 1;
for(int i = h2[u]; ~i; i = ne2[i]) {
int v = e2[i], x = w2[i];
if(dis2[v] > d + x) {
dis2[v] = d + x;
q.push({dis2[v],v});
}
}
}
int res = 0;
for(int i = 1; i <= n; ++i) {
res = max(res, dis1[i] + dis2[i]);
}
cout<<res<<endl;
}
标签:tmp,dis1,dis2,Cow,int,h2,vis,USACO07FEB,P1821
From: https://blog.csdn.net/qq_63432403/article/details/137064073