题解 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;
}