(2020-01-01)
代码如下(1到n的次短路):
#include
#include
#include
#define maxn 5005
#define maxm 200005
#define inf 0x7fffffff
#define ri register int
using namespace std;
priority_queue<pair<int,int> >q;
int from[maxm];//边的起点
int to[maxm];//边的终点
int weight[maxm];//边的权值
int next[maxm];//下一条边的编号
int head[maxn];//上一条边的编号
int vis[maxn];//判断该点是否已经找到最小值
int dis[maxn];
int dis1[maxn];//1到每个点的最短路
int dis2[maxn];//n到每个点的最短路
int n,m,t,cnt,k,ans=inf;
inline int read()//快读
{
ri x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void add_edge(int x,int y,int z)//建边
{
cnt++;
from[cnt]=x;
to[cnt]=y;
weight[cnt]=z;
next[cnt]=head[x];
head[x]=cnt;
}
inline void Dijkstra(int s,int t)
{
memset(vis,0,sizeof(vis));
for(ri i=0;i<=n;++i)
dis[i]=inf;
dis[s]=0;
q.push(make_pair(-dis[s],s));
do
{
k=q.top().second;
q.pop();
if(vis[k]) continue;
vis[k]=1;
for(ri i=head[k];i;i=next[i])//遍历每条边
{
ri v=to[i];
ri w=dis[k]+weight[i];
if(w<dis[v])
{
dis[v]=w;//更新最短路
q.push(make_pair(-dis[v],v));
vis[v]=0;
}
}
}while(q.size());//判断队列是否为空
}
int main()
{
n=read(),m=read();
for(ri i=1,x,y,z;i<=m;++i)
{
x=read(),y=read(),z=read();
add_edge(x,y,z);
add_edge(y,x,z);
}
Dijkstra(1,n);
for(ri i=1;i<=n;++i)
dis1[i]=dis[i];
Dijkstra(n,1);
for(ri i=1;i<=n;++i)
dis2[i]=dis[i];
for(ri i=1;i<=m*2;++i)
{
ri u=from[i],v=to[i],w=weight[i];
ri k=dis1[u]+dis2[v]+w;//1到u的最短路,加上v到n的最短路,再加上w
if(k>dis1[n]&&k<ans) ans=k;//更新次短路
}
printf("%d",ans);
return 0;
}
#include
#include
#include
#define maxn 5005
#define maxm 200005
#define ri register int
#define inf 0x7fffffff
using namespace std;
priority_queue<pair<int,int> >q;//定义优先队列
int to[maxm];//边的终点
int weight[maxm];//边的权值
int next[maxm];//下一条边的编号
int head[maxn];//上一条边的编号
int dis1[maxn];//1到每个点的最短路
int dis2[maxn];//1到每个点的次短路
int n,m,cnt;
inline int read()//快读
{
ri f=1,x=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void add_edge(int u,int v,int w)//建边
{
to[++cnt]=v;
weight[cnt]=w;
next[cnt]=head[u];
head[u]=cnt;
}
void dijkstra()
{
dis1[1]=0;
q.push(make_pair(-dis1[1],1));
while(!q.empty())
{
ri k=q.top().second,ki=-q.top().first;//因为进去的取了相反数,所以出来要添负号
q.pop();
if(dis2[k]<ki) continue;//如果该点的次短路已经比要更新的小了,那么就不需要更新
for(ri i=head[k];i;i=next[i])
{
ri v=to[i],s=ki+weight[i];
if(s<dis1[v])
{
dis1[v]=s;//更新最短路
q.push(make_pair(-dis1[v],v));
}
if(s>dis1[v]&&s<dis2[v])//比最短路长并且比次短路短
{
dis2[v]=s;//更新次短路
q.push(make_pair(-dis2[v],v));
}
}
}
}
int main()
{
n=read(),m=read();
for(ri i=1,x,y,z;i<=m;++i)
{
x=read(),y=read(),z=read();
add_edge(x,y,z);
add_edge(y,x,z);
}
for(ri i=1;i<=n;++i) dis1[i]=dis2[i]=inf;//都赋最大值
dijkstra();
printf("%d",dis2[n]);
return 0;
}
两道练习题
洛谷P2865
洛谷P2829