[KuangBin专题四]Silver Cow Party
Silver Cow Party
原题链接:传送门
题目大意
给定一幅有向图,要求你求出从每个点出发到点x的最短路和从x回到每个点的最短路径和最大为多少?
分析
这个题目可以分成两个部分来考虑
1.从x到其他每个点的最短路径
对于这种情况我们只需要以x为源点跑一遍最短路即可。
2.从其他点到x的最短路径
我们可以反向建图,在跑一遍从其他点到 x 的最短路径。
AC 代码
C++ code
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1005;
const int M = 100005;
struct edge{
int w , to , next;
}e[M] , re[M];
int head[N] , rhead[N];
int tot , rtot;
int dis[N] , rdis[N];
int vis[N] , rvis[N];
int n , m , x;
void add(int a,int b,int c)
{
e[++tot].to = b;
e[tot].w = c;
e[tot].next = head[a];
head[a] = tot;
}
void radd(int a,int b,int c)
{
re[++rtot].to = b;
re[rtot].w = c;
re[rtot].next = rhead[a];
rhead[a] = rtot;
}
void spfa(int s)
{
memset(dis , 0x3f , sizeof dis);
memset(vis , 0 , sizeof vis);
queue<int> q;dis[s] = 0;
q.push(s);vis[s] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
vis[x] = 0;
for(int i = head[x] ; i != -1 ;i = e[i].next)
{
int y = e[i].to , w = e[i].w;
if(dis[y] > dis[x] + w)
{
dis[y] = dis[x] + w;
if(!vis[y])q.push(y) , vis[y] = 1;
}
}
}
}
void rspfa(int s)
{
memset(rdis , 0x3f , sizeof rdis);
memset(rvis , 0 , sizeof rvis);
queue<int> q;rdis[s] = 0;
q.push(s);rvis[s] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
rvis[x] = 0;
for(int i = rhead[x] ; i != -1 ;i = re[i].next)
{
int y = re[i].to , w = re[i].w;
if(rdis[y] > rdis[x] + w)
{
rdis[y] = rdis[x] + w;
if(!rvis[y])q.push(y) , rvis[y] = 1;
}
}
}
}
int main()
{
memset(head , -1 , sizeof head);
memset(rhead , -1 , sizeof rhead);
cin >> n >> m >> x;
for(int i = 0;i < m ;i ++)
{
int a , b , c;
cin >> a >> b >> c;
add(a , b , c);
radd(b , a , c);
}
spfa(x);rspfa(x);
int ans = 0;
for(int i = 1;i <= n ;i ++)
{
ans = max(ans , dis[i] + rdis[i]);
}
cout << ans << endl;
return 0;
}