首页 > 代码库 > 【最短路】【spfa】hdu6071 Lazy Running

【最短路】【spfa】hdu6071 Lazy Running

给你一个4个点的环,问你从2号点出发, 再回到2号点,长度>=K的最短路是多少。环上的边长度不超过30000。

技术分享

跑出来所有dis(2,j)以后,然后for一遍j,根据dis(2,j)+t*2*w>=K,解出来对于每个j而言最小的t,然后尝试更新答案即可。如果dis(2,j)已经大于等于K了,那直接用其尝试更新答案。

跟CDOJ1633很像。

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll ans,K;
int W,T,a[4];
typedef pair<int,int> Point;
queue<Point>q;
bool inq[4][60010];
int dis[4][60010];
void spfa()
{
	memset(dis,0x7f,sizeof(dis));
	memset(inq,0,sizeof(inq));
	q.push(make_pair(1,0)); inq[1][0]=1; dis[1][0]=0;
	while(!q.empty()){
		Point U=q.front();
		Point V=make_pair((U.first+1)%4,(U.second+a[U.first])%(2*W));
		if(dis[V.first][V.second]>dis[U.first][U.second]+a[U.first]){
			dis[V.first][V.second]=dis[U.first][U.second]+a[U.first];
			if(!inq[V.first][V.second]){
				q.push(V);
				inq[V.first][V.second]=1;
			}
		}
		V=make_pair((U.first+3)%4,(U.second+a[(U.first+3)%4])%(2*W));
		if(dis[V.first][V.second]>dis[U.first][U.second]+a[(U.first+3)%4]){
			dis[V.first][V.second]=dis[U.first][U.second]+a[(U.first+3)%4];
			if(!inq[V.first][V.second]){
				q.push(V);
				inq[V.first][V.second]=1;
			}
		}
		q.pop();
		inq[U.first][U.second]=0;
	}
}
int main(){
//	freopen("1005.in","r",stdin);
//	freopen("1005.out","w",stdout);
	scanf("%d",&T);
	for(;T;--T){
		ans=9000000000000000000ll;
		scanf("%lld",&K);
		for(int i=0;i<4;++i){
			scanf("%d",&a[i]);
		}
		W=min(a[1],a[0]);
		spfa();
		for(int i=0;i<2*W;++i){
			if(dis[1][i]<2000000000){
//				printf("%d: (%d)\n",i,dis[1][i]);
				if(dis[1][i]<K){
					ans=min(ans,(ll)dis[1][i]+(ll)(2*W)*((K-(ll)dis[1][i])/(ll)(2*W)+(ll)((K-(ll)dis[1][i])%(ll)(2*W)!=0)));
				}
				else{
					ans=min(ans,(ll)dis[1][i]);
				}
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

【最短路】【spfa】hdu6071 Lazy Running