Description


题解:分数规划+spfa判负环。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 3010
#define M 10010
#define exp 1e-9
using namespace std;
struct use{int en;double v,w;}e[M];
int point[N],next[M],cnt,x,y,vis[N],p,n,m;
double v,l,r,dis[N];
void add(int x,int y,double v){
next[++cnt]=point[x];point[x]=cnt;
e[cnt].en=y;e[cnt].w=e[cnt].v=v;
}
void build(double x){
for (int i=1;i<=n;i++)
for (int j=point[i];j;j=next[j])
e[j].v=e[j].w-x;
}
void spfa(int x){
vis[x]=1;
for (int i=point[x];i;i=next[i])
if (dis[e[i].en]>dis[x]+e[i].v){
if (vis[e[i].en]){p=1;return;}
else {dis[e[i].en]=dis[x]+e[i].v;spfa(e[i].en);}
}
vis[x]=0;
}
bool check(){
memset(dis,127/3,sizeof(dis));memset(vis,0,sizeof(vis));p=0;
for (int i=1;i<=n;i++){spfa(i);if (p) return true;}
return false;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){scanf("%d%d%lf",&x,&y,&v);add(x,y,v);}
l=-1000000000;r=1000000000;
while (r-l>exp){
double mid=(l+r)/2;build(mid);
if (check()) r=mid;else l=mid;
}
printf("%.8lf",l);
}