[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;
}
原文地址:https://www.cnblogs.com/wlw-x/p/13765114.html