贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。 贝茜所在的乡村有R(1<=R<=100,000)条双向道路,每条路都联结了所有的N(1<=N<=5000)个农场中的某两个。贝茜居住在农场1,她的朋友们居住在农场N(即贝茜每次旅行的目的地)。 贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。
一个裸的次短路,很简单。
求出起点和终点的单源最短路。
枚举每一条边,表示必经过这条边的最短路,若这条路径大于原最短路,则可能为次短路,取个 M i n Min Min值即可
#include
#define N 5005
#define ll long long
using namespace std;
int n,r,ans=1e9;
int dis[2][N],ax[N*40],ay[N*40],aw[N*40];
queue<int> q;
bool vis[N];
int ls[N],cnt;
struct node
{
int v,next,w;
}a[N*40];
void add(int x,int y,int w)
{
a[++cnt].v=y;a[cnt].w=w;a[cnt].next=ls[x];ls[x]=cnt;
}
void spfa(int s)
{
int x=0;
if(s==n) x=1;
dis[x][s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=0;
for(int i=ls[u];i;i=a[i].next)
{
int v=a[i].v;
if(dis[x][u]+a[i].w<dis[x][v])
{
dis[x][v]=dis[x][u]+a[i].w;
if(!vis[v])
vis[v]=1,q.push(v);
}
}
}
}
int main()
{
freopen("block.in","r",stdin);
freopen("block.out","w",stdout);
cin>>n>>r;
for(int i=1,x,y,w;i<=r;i++)
{
cin>>x>>y>>w;
ax[i]=x;ay[i]=y;aw[i]=w;
add(x,y,w);add(y,x,w);
}
memset(dis,0x3f,sizeof(dis));
spfa(1);spfa(n);
for(int i=1;i<=r;i++)
{
int xx=dis[0][ax[i]]+aw[i]+dis[1][ay[i]],yy=dis[0][ay[i]]+aw[i]+dis[1][ax[i]];
if(xx!=dis[0][n]) ans=min(ans,xx);
if(yy!=dis[0][n]) ans=min(ans,yy);
}
cout<<ans;
return 0;
}