题目大意:求出DAG中次短路的长。
题目分析:两遍SPFA
其中Dist1[i]表示1节点到i节点的最短路
Dist2[j]表示节点j到节点N的最短路
设w为i->j的权值,ans1为最短路径
然后寻找最接近ans1的次短路径。
如下代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define MAXN 5500
#define INF 1000000
using namespace std;
struct Edge
{
int v,w;
Edge(int vv,int ww):v(vv),w(ww){}
};
int dist1[MAXN],dist2[MAXN];
bool mark[MAXN];
int n,m;
vector<vector<Edge> > map;
void SPFA(int u,int dist[])
{
memset(mark,false,(n+2)*sizeof(bool));
for(int i=1;i<=n;i++)dist[i]=INF;
dist[u]=0;
queue<int>Q;
Q.push(u);
while(!Q.empty()){
u=Q.front();
Q.pop();
mark[u]=false;
for(int i=0;i<map[u].size();i++){
int v=map[u][i].v,w=map[u][i].w;
if(dist[u]+w<dist[v]){
dist[v]=dist[u]+w;
if(!mark[v]){
mark[v]=true;
Q.push(v);
}
}
}
}
}
/*id SPFA(int u,int dist[])
{
memset(V,false,sizeof(V));
for(int i=1;i<=n;i++)
dist[i]=INF;
dist[u]=0;
queue<int>Q;
Q.push(u);
while(!Q.empty())
{
u=Q.front();
Q.pop();
V[u]=false;
for(int i=0;i<map[u].size();i++)
{
int v=map[u][i].v;
int w=map[u][i].w;
if(dist[u]+w<dist[v])
{
dist[v]=dist[u]+w;
if(!V[u])
{
V[u]=true;
Q.push(v);
}
}
}
}
}*/
int main()
{
int u,v,w,ans1,ans2;
while(scanf("%d%d",&n,&m)!=EOF)
{
map.clear();
map.resize(n+2);
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
map[u].push_back(Edge(v,w));
map[v].push_back(Edge(u,w));
}
SPFA(1,dist1);
SPFA(n,dist2);
ans1=ans2=INF;
for(int u=1;u<=n;u++)
for(int i=0;i<map[u].size();i++)
{
int v=map[u][i].v;
int w=map[u][i].w;
if(dist1[u]+dist2[v]+w<ans1)
{
ans2=ans1;
ans1=dist1[u]+dist2[v]+w;
}
else if(dist1[u]+dist2[v]+w<ans2&&dist1[u]+w+dist2[v]!=ans1)
{
ans2=dist1[u]+w+dist2[v];
}
}
printf("%d\n",ans2);
}
//while(1);
return 0;
}