【题解】codevs P2645 Spore(spfa 负环)

一开始以为这是比较裸的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;
}

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81138640