BZOJ2763 [JLOI2011]飞行路线(分层图最短路)

【题解】

设 d[i][j]为到达结点i,免费票用掉j张时,花费的最小值 
则 d[i][j]可以更新 d[k][j] (i与k有边相连),若j<k,还可以更新 d[k][j+1]
注意总共会产生n*k=10^5种状态,SPFA算法,队列要开大一些,10^7可过,或者循环队列 
还有SPFA会跑的很慢,"Spfa不适和分层图" ──贴吧 


【代码】

#include<stdio.h>
#include<stdlib.h>
#define INF 1000000000
int d[10005][15],q[10000005],v[100005],w[100005],first[10005],next[100005],hash[1000020];
int e=0;
void tj(int x,int y,int z)
{
	v[++e]=y;
	w[e]=z;
	next[e]=first[x];
	first[x]=e;
}
int main()
{
	int n,m,k,s,t,i,j,head=0,tail=1,x,y,z,ans=INF;
	scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		tj(x,y,z);
		tj(y,x,z);
	}
	for(i=0;i<n;i++)
		for(j=0;j<=k;j++)
			d[i][j]=INF;
	d[s][0]=0;
	q[0]=s<<4;//编码 233
	hash[s<<4]=1;
	while(head<tail)
	{
		x=q[head]>>4;//解码 233
		y=q[head]&15;
		for(i=first[x];i!=0;i=next[i])
		{
			if(y<k)
				if(d[v[i]][y+1]>d[x][y])
				{
					d[v[i]][y+1]=d[x][y];
					z=v[i]<<4|y+1;//编码 233
					if(hash[z]==0)
					{
						q[tail++]=z;
						hash[z]=1;
					}
				}
			if(d[v[i]][y]>d[x][y]+w[i])
			{
				d[v[i]][y]=d[x][y]+w[i];
				z=v[i]<<4|y;
				if(hash[z]==0)
				{
					q[tail++]=z;
					hash[z]=1;
				}
			}
		}
		hash[q[head++]]=0;
	}
	for(i=0;i<=k;i++)
		if(ans>d[t][i]) ans=d[t][i];
	printf("%d",ans);
	return 0;
}


你可能感兴趣的:(分层最短路)