jzoj 1224. 最小密度路径 Description Input Output Sample Input Sample Output Hint solution code

这次的任务很简单,给出了一张有N个点M条边的加权有向无环图,接下来有Q个询问,每个询问包括2个节点X和Y,要求算出从X到Y的一条路径,使得密度最小(密度的定义为,路径上边的权值和除以边的数量)。

Input

第一行包括2个整数N和M。
以下M行,每行三个数字A、B、W,表示从A到B有一条权值为W的有向边。
再下一行有一个整数Q。
以下Q行,每行一个询问X和Y,如题意所诉。

Output

对于每个询问输出一行,表示该询问的最小密度路径的密度(保留3位小数),如果不存在这么一条路径输出“OMG!”(不含引号)。

Sample Input

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

Sample Output

5.000
5.500

Hint

【数据规模】
对于60%的数据,有1 ≤ N ≤ 10,1 ≤ M ≤ 100,1 ≤ W ≤ 1000,1 ≤ Q ≤ 1000;
对于100%的数据,有1 ≤ N ≤ 50,1 ≤ M ≤ 1000,1 ≤ W ≤ 100000,1 ≤ Q ≤ 100000。

solution

这题一看:不就是个二分+判断嘛,简单!
结果,时超GG!

code(T的)

#include<cstdio>
#include<algorithm>
#define db double
using namespace std;
struct node{int v,fr,w;}e[1010];
int n,m,tail[51],cnt=0,x,y;
db ans,l,r,mid;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

void add(int u,int v,int w) {e[++cnt]=(node){v,tail[u],w}; tail[u]=cnt;}

bool check(int x,db s,db del)
{
	if (x==y) return s<=0.0;
	bool bz;
	for (int p=tail[x];p;p=e[p].fr)
	{
		bz=check(e[p].v,s+e[p].w-del,del);
		if (bz) return 1;
	}
	return 0;
}

int main()
{
	n=read(),m=read();
	for (int i=1,u,v,w;i<=m;i++)
		u=read(),v=read(),w=read(),add(u,v,w);
	for (int Q=read();Q;Q--)
	{
		x=read(),y=read();
		if (x==y)
		{
			puts("0");
			continue;
		}
		l=1,r=100001;
		while (l+0.0001<=r)
		{
			mid=(l+r)/2.0;
			if (check(x,0,mid)) r=mid;
			else l=mid;
		}
		if (r==100001.0) puts("OMG!"); 
		else printf("%.3lf
",r);
	}
	return 0;
}

后来听了讲,说是floyd就可以了,n4预处理然后再一个n2预处理即可。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define db double
using namespace std;
int n,m,Q,x,y,f[51][51][51];
db ans,answer[51][51];
bool bz[51][51];

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

int main()
{
	freopen("path1.in","r",stdin);
	freopen("path.out","w",stdout);
	n=read(),m=read();
	memset(f,10,sizeof(f));
	for (int i=1,u,v,w;i<=m;i++)
		u=read(),v=read(),w=read(),f[u][v][1]=min(f[u][v][1],w);
	for (int t=2;t<=n;t++)
		for (int k=1;k<=n;k++)
			for (int i=1;i<=n;i++)
				for (int j=1;j<=n;j++)
					f[i][j][t]=min(f[i][j][t],f[i][k][t-1]+f[k][j][1]);
	scanf("%d",&Q);
	while (Q--)
	{
		scanf("%d%d",&x,&y);
		if (!bz[x][y])
		{
			ans=(1<<30);
			for (int i=1;i<=n;i++)
				ans=min(ans,(db)f[x][y][i]/i);
			answer[x][y]=ans,bz[x][y]=1;
		}
		else ans=answer[x][y];
		if (ans>100000.0) puts("OMG!");
		else printf("%.3lf
",ans);
	}
	return 0;
}