Time Limits: 1000 ms Memory Limits: 65536 KB
Description
N头牛要去参加一场在编号为x(1<=x<=n)的牛的农场举行的派对(1<=N<=1000),有M(1<=m<=100000)条有向道路,每条路长ti(1<=ti<=100);
每头牛都必须参加完派对后回到家,每头牛都会选择最短路径,求这n个牛的最短路径(一个来回)中最长的一条的长度。
特别提醒:可能有权值不同的重边。
Input
第1行: N,M,X;
第2~m+1行: Ai,Bi,Ti,表示有一条从Ai到Bi的路,长度为Ti.
Output
最长最短路的长度。
Sample Input
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
Sample Output
10
一看就应该知道是SPFA,而不用Floyd,亏某位刘某昊同学还用Floyd骗了80。
存一组边,另一组存反过来的边,以Party的位置开始SPFA,两次分别求出去世的最短路径和回时的最短路径,再求答案即可。
#include
#include
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int Groad[100001][4],Broad[100001][4],Gfir[1001],Glas[1001],Bfir[1001],Blas[1001],fg[1001],fb[1001],data[400000];
bool bz[1001];
void GetThere(int);
void GetHere(int);
void insert(int,int,int,int);
int main()
{
memset(fb,0x7f,sizeof(fb));
memset(fg,0x7f,sizeof(fg));
int n,m,x,ans=0;
scanf("%d%d%d",&n,&m,&x);
fo(i,1,m)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
insert(i,a,b,c);
}
GetHere(x);GetThere(x);
fo(i,1,n)ans=max(ans,fg[i]+fb[i]);
printf("%d",ans);
}
void insert(int p,int x,int y,int z)
{
Groad[p][0]=x;Groad[p][1]=y;Groad[p][2]=z;Groad[p][3]=p;
Broad[p][0]=y;Broad[p][1]=x;Broad[p][2]=z;Broad[p][3]=p;
if(Gfir[x]==0)Gfir[x]=p; else Groad[Glas[x]][3]=p;
if(Bfir[y]==0)Bfir[y]=p; else Broad[Blas[y]][3]=p;
Glas[x]=Blas[y]=p;
}
void GetThere(int s)
{
int h=0,t=1;
data[1]=s;
memset(bz,1,sizeof(bz));
bz[s]=0;fg[s]=0;
while(hint now=data[h],v=fg[now],o=Gfir[now];
if(o<1)continue;
while(1)
{
int x=Groad[o][1],va=v+Groad[o][2];
if(vaif(bz[x])
{
bz[x]=0;
t++;
data[t]=x;
}
}
if(o==Groad[o][3])break;
o=Groad[o][3];
}
bz[now]=1;
}
}
void GetHere(int s)
{
int h=0,t=1;
data[1]=s;
memset(bz,1,sizeof(bz));
bz[s]=0;fb[s]=0;
while(hint now=data[h],v=fb[now],o=Bfir[now];
if(o<1)continue;
while(1)
{
int x=Broad[o][1],va=v+Broad[o][2];
if(vaif(bz[x])
{
bz[x]=0;
t++;
data[t]=x;
}
}
if(o==Broad[o][3])break;
o=Broad[o][3];
}
bz[now]=1;
}
}