01分数规划+二分答案+spfa判负环
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 3005 #define maxm 10005 #define inf 1000000000 #define eps 1e-9 using namespace std; struct edge{int next,to;double v,w;}e[maxm]; int n,m,cnt,head[maxn]; double dis[maxn]; bool flag,mark[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add_edge(int x,int y) { e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt; } inline void spfa(int x) { if (mark[x]){flag=true;return;} mark[x]=true; for(int i=head[x],y;i;i=e[i].next) if (dis[x]+e[i].v<dis[y=e[i].to]) { dis[y]=dis[x]+e[i].v; spfa(y); if (flag) return; } mark[x]=false; } inline bool judge() { F(i,1,n) dis[i]=mark[i]=0; flag=false; F(i,1,n) { spfa(i); if (flag) return true; } return false; } int main() { n=read();m=read(); int x,y;double z,l=inf,r=-inf,mid; F(i,1,m) { x=read();y=read();scanf("%lf",&z); add_edge(x,y); e[i].w=z; l=min(l,z); r=max(r,z); } while (r-l>=eps) { mid=(l+r)/2; F(i,1,m) e[i].v=e[i].w-mid; if (judge()) r=mid; else l=mid; } printf("%.8lf\n",l); return 0; }