一开始以为这是比较裸的spfa模板题,写上去之后只有20分,原因何在?
再读一遍题我们发现这道题可能有负环存在,而如果有负环存在,那最小值就会沿着这个环一直减小。。所以我们需要判断负环。设一个cnt数组统计一个数进入队列的次数,初始化cnt[1]=1。当寻找最短路向外扩展时cnt[y]=cnt[x]+1。如果这个图是链状结构走到终点,那cnt[n]应当=n,但如果有负环存在的话,那cnt[n]一定>n,所以我们在cnt+1后判断当前cnt是否大于n 大于n就存在负环 return true,否则return false 如果spfa()返回true或没有到n的路径,那就输出No such path,否则输出结果即可
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=1010;
const int maxm=10010;
int n,m;
int head[maxn],nnext[maxm*2],to[maxm*2],team[maxn],length[maxm*2],dis[maxn],cnt[maxn];
bool b[maxn];
int tot,s=0,t=0;
void add(int x,int y,int l)
{
tot++;
nnext[tot]=head[x];
head[x]=tot;
to[tot]=y;
length[tot]=l;
}
bool spfa(int x)
{
for(int i=1;i<=n;i++)
{
dis[i]=1e9;
}dis[1]=0;
team[t]=1;
t++;
b[1]=true;
cnt[1]=1;
while(s!=t)
{
int now=team[s];
s++;
s%=n;
b[now]=false;
for(int i=head[now];i;i=nnext[i])
{
int y=to[i];
if(dis[y]>dis[now]+length[i])
{
dis[y]=dis[now]+length[i];
if(b[y]==false)
{
team[t]=y;
t++;
t%=n;
b[y]=true;
cnt[y]=cnt[now]+1;
if(cnt[y]>n) return true;
}
}
}
}
return false;
}
int main()
{
while((cin>>n>>m)&&n!=0)
{
memset(head,0,sizeof(head));
tot=0;
memset(team,0,sizeof(team));
memset(b,false,sizeof(b));
s=0,t=0;
for(int i=1;i<=m;i++)
{
int g1,g2,c1,c2;
cin>>g1>>g2>>c1>>c2;
add(g1,g2,c1);
add(g2,g1,c2);
}
bool ff=spfa(1);
if(ff==true||dis[n]==1e9)
{
cout<<"No such path"<<endl;
}
else cout<<dis[n]<<endl;
}
return 0;
}