1. 程式人生 > >最小密度路徑 洛谷p1730

最小密度路徑 洛谷p1730

題目描述

給出一張有N個點M條邊的加權有向無環圖,接下來有Q個詢問,每個詢問包括2個節點X和Y,要求算出從X到Y的一條路徑,使得密度最小(密度的定義為,路徑上邊的權值和除以邊的數量)。

輸入輸出格式

輸入格式:

第一行包括2個整數N和M。

以下M行,每行三個數字A、B、W,表示從A到B有一條權值為W的有向邊。

再下一行有一個整數Q。

以下Q行,每行一個詢問X和Y,如題意所訴。

輸出格式:

對於每個詢問輸出一行,表示該詢問的最小密度路徑的密度(保留3位小數),如果不存在這麼一條路徑輸出“OMG!”(不含引號)。

輸入輸出樣例

輸入樣例#1: 複製

3 3
1 3 5
2 1 6
2 3 6
2
1 3
2 3

輸出樣例#1: 複製

5.000
5.500

說明

1 ≤ N ≤ 50,1 ≤ M ≤ 1000,1 ≤ W ≤ 100000,1 ≤ Q ≤ 100000

f[i][j][h]=min(f[i][[k][1]+f[k][j][h-1]),表示從i到j經過h條路徑的最短路,轉移時列舉斷點k,強制使k表示路徑上離i最近的點。

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=55,INF=1000000000;
int dis[MAXN][MAXN][1005];
int n,m,Q;
int main()
{
	ios::sync_with_stdio(false);
	int i,j,k,u,v,w,t,tt;
	memset(dis,60,sizeof(dis));
	cin>>n>>m;
	f(i,1,m){
		cin>>u>>v>>w;
		dis[u][v][1]=min(dis[u][v][1],w);
	}
	f(t,2,m){
		f(k,1,n){
			f(i,1,n){
				f(j,1,n){
					if(dis[i][k][1]>INF||dis[k][j][t-1]>INF) continue;
					dis[i][j][t]=min(dis[i][j][t],dis[i][k][1]+dis[k][j][t-1]);
				}	
			}
		}
	}
	cin>>Q;
	f(i,1,Q){
		cin>>u>>v;
		double ans=INF;
		f(j,1,m){
			if(dis[u][v][j]>INF) continue;
			ans=min(ans,1.0*dis[u][v][j]/j);
		}
		if(ans==INF) cout<<"OMG!"<<endl;
		else cout<<fixed<<setprecision(3)<<ans<<endl;
	}
	return 0;
}