hdu6331(最短路)

题意:给你一个有向图让你,有q次查询让你求从u到v至少经过k条路径的最短路径。

题解:这里注意到我们最大的环就是1->2->3->n....->1这样一个n条路径的环,所以当经过k~k+n条路径找不到答案的话就肯定没有结果,因为k最大10000所以我们根据分块思想分成\sqrt{100},也就是每100分成一块,那么我们可以预处理f[i][j][k],表示走了i×100条路径j到k的最短路径,然后我们还剩下的是k%100~k%100+n条这些情况下的答案,所以我们要预处理一下dp[i][j][k]表示至少走了i条路径j到k的最短路径。因为k%100+n最大是149所以我们要预处理1~149路径的情况,最大的块数是100所以要处理100块。最后查询的时候枚举每个中间点然后答案就是\min{\sum_{i=1}^{n}f[\left \lfloor k/100 \right \rfloor][u][i]+dp[k-\left \lfloor k/100 \right \rfloor*100][i][v]}

时间复杂度是O(150n^3+qn)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<stack>
#include<bitset>
using namespace std;
#define mes(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dec(i,a,b) for(int i = a; i >= b; i--)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define lowbit(x) x&(-x)
typedef double db;
typedef long long int ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const ll inf = 0x3f3f3f3f;
const int mx = 1e5+5;
const int mod = 1e9+7;
const int x_move[] = {1,-1,0,0,1,1,-1,-1};
const int y_move[] = {0,0,1,-1,1,-1,1,-1};
int n,m;
ll mp[55][55];
ll dp[155][55][55];
ll f[105][55][55];
int main(){
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	int t,q,ca = 1;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		mes(mp,63);
		mes(dp,63);
		mes(f,63);
		rep(i,1,m){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			mp[u][v] = min(mp[u][v],1ll*w);
		}
		rep(i,1,n)
			dp[0][i][i] = f[0][i][i] = 0;
		rep(i,1,150)	
			rep(j,1,n)
				rep(s,1,n)
					rep(e,1,n)
						dp[i][s][e] = min(dp[i][s][e],dp[i-1][s][j]+mp[j][e]);
		rep(i,1,100)
			rep(j,1,n)
				rep(s,1,n)
					rep(e,1,n)
						f[i][s][e] = min(f[i][s][e],f[i-1][s][j]+dp[100][j][e]);
		dec(i,149,0)
			rep(j,1,n)
				rep(k,1,n)
					dp[i][j][k] = min(dp[i][j][k],dp[i+1][j][k]);
		scanf("%d",&q);
		while(q--){
			int u,v,k;
			scanf("%d%d%d",&u,&v,&k);
			int a = k/100;
			int b = k%100;
			ll ans = inf;
			rep(i,1,n)
				ans = min(ans,f[a][u][i]+dp[b][i][v]);
			if(ans==inf)
				puts("-1");
			else
				printf("%lld\n",ans);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1325136367/article/details/81317686
今日推荐