题目:
题解:
相当于是
∑wij∑1<L
∑
w
i
j
∑
1
<
L
要求更小的啊,然后
∑wij−L<0
∑
w
i
j
−
L
<
0
那就是一个图的01分数规划了,如果有负环说明可以更小
注意求负环的时候dis数组要设为0,这样快很多
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=3005;
const int M=10005;
int tot,nxt[M],point[N],v[M],n;
double c[M],dis[N];bool vis[N],fff;
void addline(int x,int y,double z){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;}
void spfa(int now,double mid)
{
vis[now]=1;
for (int i=point[now];i;i=nxt[i])
if (dis[v[i]]>dis[now]+c[i]-mid && !fff)
{
dis[v[i]]=dis[now]+c[i]-mid;
if (vis[v[i]]) {fff=1;return;}
spfa(v[i],mid);
}
vis[now]=0;
}
bool check(double mid)
{
fff=0;
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;i++)
{
spfa(i,mid);
if (fff) return 1;
}
return 0;
}
int main()
{
int m;scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y;double w;scanf("%d%d%lf",&x,&y,&w);
addline(x,y,w);
}
double l=-10000000,r=10000000;
while (r-l>1e-10)
{
double mid=(l+r)/2;
if (check(mid)) r=mid;
else l=mid;
}
printf("%.8lf",l);
}