题解 codevs 1992 聚会

这题数据实在是水,但是为了装逼所以也用 SPFA (光速逃

因为是有去有回,所以分两段考虑,一段来一段去,所以做两次SPFA就行了。

具体实现的话用邻接表,a,b 数组存储与这个点相关联的边的个数,aw,bw 数组存储每条边的值。

接下来跑两次 SPFA ,来回的最短路径分别用min1,min2表示,之后加起来求个最小值就完事了。

AC code

#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,ans,a[1233][1233],aw[1233][1233],k,b[1233][1233],ansx,bw[1233][1233],min1[1233],min2[1233],bo[1233],z,u;
queue<int> q;
void init()
{
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		a[x][++a[x][0]]=y;
		aw[x][a[x][0]]=z;
		b[y][++b[y][0]]=x;
		bw[y][b[y][0]]=z;
	}
}
void spfa1()
{
	memset(min1,0x3f,sizeof(min1));
	bo[k]=1;min1[k]=0;
	q.push(k);
	while(!q.empty())
	{
		u=q.front();q.pop();
		bo[u]=0;
		for(int i=1;i<=a[u][0];i++)
		{
			if(min1[a[u][i]]>min1[u]+aw[u][i])
			{
				min1[a[u][i]]=min1[u]+aw[u][i];
				if(bo[a[u][i]]==0)
				{
					bo[a[u][i]]=1;
					q.push(a[u][i]);
				}
			}
		}
	}
}
void spfa2()
{
	memset(min2,0x3f,sizeof(min2));
	bo[k]=1;min2[k]=0;
	q.push(k);
	while(!q.empty())
	{
		u=q.front();q.pop();
		bo[u]=0;
		for(int i=1;i<=b[u][0];i++)
		{
			if(min2[b[u][i]]>min2[u]+bw[u][i])
			{
				min2[b[u][i]]=min2[u]+bw[u][i];
				if(bo[b[u][i]]==0)
				{
					bo[b[u][i]]=1;
					q.push(b[u][i]);
				}
			}
		}
	}
}
void work()
{
	ans=0x3f3f3f3f;
	for(int i=1;i<=n;i++)
	  if(ansx<min1[i]+min2[i]&&min1[i]!=ans&&min2[i]!=ans) ansx=min1[i]+min2[i];
	cout<<ansx;
}
int main()
{
	init();
	spfa1();
	spfa2();
	work();
	return 0;
}
posted @ 2020-03-30 13:37  Akn_Wind  阅读(126)  评论(0编辑  收藏  举报