关于答案我们可以二分一下,把原值都减去二分的值之后假如还存在负环的话就说明答案可以更小一点。
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
#define eps 1e-9
#define maxn 10010
int first[maxn],to[maxn],next[maxn],e,n,m,vis[maxn],flag;
double val[maxn],val1[maxn],dis[maxn];
int getint()
{
int res;char c;
while(c=getchar(),c<'0'||c>'9');
res=c-'0';
while(c=getchar(),c>='0'&&c<='9')
res=res*10+c-'0';
return res;
}
void build(int a,int b,double c)
{
e++;
to[e]=b;val[e]=c;
next[e]=first[a];
first[a]=e;
}
void dfs(int now)
{
vis[now]=1;
int v;
for(int i=first[now];i;i=next[i])
{
v=to[i];
if(dis[v]>dis[now]+val1[i])
{
if(vis[v]) {flag=1;return;}
dis[v]=dis[now]+val1[i];
dfs(v);
if(flag) return;
}
}
vis[now]=0;
}
bool judge(double len)
{
flag=0;
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
for(int i=1;i<=e;i++) val1[i]=val[i]-len;
for(int i=1;i<=n;i++)
{
dfs(i);
if (flag)return 0;
}
return 1;
}
int main()
{
int a,b;
n=getint();
m=getint();
double l,r,ans,mid,c;
l=-1000000000;
r=1000000000;
for(int i=1;i<=m;i++)
{
a=getint();
b=getint();
scanf("%lf",&c);
//l=min(l,c);
//r=max(r,c);
build(a,b,c);
}
while(r-l>eps)
{
mid=(l+r)/2;
if(judge(mid))
{
ans=mid;
l=mid;
}
else
{
r=mid;
}
}
printf("%.8f",ans);
return 0;
}
/*
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
*/