思路:跑堆优化版dijkstra,从x到其他任意点,然后其他n-1个点跑一个dijkstra到x点,两者相加求最大值,复杂度 O ( n l o g ( m ) ) O(nlog(m)) O(nlog(m))
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
typedef pair<int, int> PII;
const int N = 1010, M = 1e5 + 10;
int e[M], w[M], ne[M], h[N], idx;
int dist[N], res[N];
bool st[N];
void add(int a, int b, int c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
inline void print(int x)
{
if(x < 0) putchar('-'), x = -x;
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
inline int read()
{
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
void dijkstra(int x) //从x去其他地方
{
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
dist[x] = 0;
priority_queue<PII, vector<PII>, greater<PII> > heap;
heap.push({dist[x], x});
while(!heap.empty())
{
int t = heap.top().second;
heap.pop();
if(st[t]) continue;
st[t] = true;
for(int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if(dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
heap.push({dist[j], j});
}
}
}
}
int main()
{
//freopen("in.txt", "r", stdin);
memset(h, -1, sizeof h);
int n, m, x;
n = read(), m = read(), x = read();
while(m--)
{
int a = read(), b = read(), c = read();
add(a, b, c);
}
dijkstra(x); //从x点到其他点的最短距离
memcpy(res, dist, sizeof dist);
int ans = -1e9;
for(int i = 1; i <= n; ++i)
if(i != x)
{
dijkstra(i); //从i点到其他点的最短距离
res[i] += dist[x];
ans = max(ans, res[i]);
}
print(ans);
return 0;
}
其实看别人的解法更优,那就是利用转置矩阵将边反向
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1010;
int g[N][N], dist[N], res[N];
bool st[N];
inline void print(int x){
if(x < 0) x = -x, putchar('-');
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
inline int read(){
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar();
}
return f * x;
}
void dijkstra(int x, int n)
{
memset(dist, 0x3f, sizeof dist) ;
memset(st, false, sizeof st);
dist[x] = 0;
for(int i = 1; i < n; ++i)
{
int t = -1;
for(int j = 1; j <= n; ++j)
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
st[t] = true;
for(int j = 1; j <= n; ++j)
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
}
int main()
{
// freopen("in.txt", "r", stdin);
int n = read(), m = read(), x = read();
memset(g, 0x3f, sizeof g);
while(m--)
{
int a = read(), b = read(), c = read();
g[a][b] = min(g[a][b], c);
}
dijkstra(x, n);
memcpy(res, dist, sizeof dist);
for(int i = 1; i < n; ++i) //转置矩阵
for(int j = i + 1; j <= n; ++j)
swap(g[i][j], g[j][i]);
dijkstra(x, n);
int ans = -1e9;
for(int i = 1; i <= n; ++i)
if(i != x)
ans = max(ans, res[i] + dist[i]);
print(ans);
return 0;
}