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;
}