题目描述
样例 1
输入
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
输出
3.66666667
样例 2
输入
2 2
1 2 -2.9
2 1 -3.1
输出
-3.00000000
#include<stdio.h>
#include<string.h>
#define ep 1e-10
int n,m,flag,tot;
int fre[10010],nxt[10010],son[10010],vis[10010];
double w[10010],dis[10010],maxx;
void add(int x,int y,double z){
son[++tot]=y;nxt[tot]=fre[x];fre[x]=tot;w[tot]=z;
}
int spfa(int s,double mid){//判环
vis[s]=1;
for(int i=fre[s];i;i=nxt[i]){
int to=son[i];
if(dis[s]+w[i]-mid<dis[to]){//如果更优,就判断是否为环
dis[to]=dis[s]+w[i]-mid;//更新
if(vis[to]||spfa(to,mid)){
vis[s]=0;
return 1;
}
}
}
vis[s]=0;
return 0;
}
bool check(double mid){
for(int i=0;i<=n;i++)
dis[i]=0.0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){//枚举起点
if(spfa(i,mid))
return 1;//存在负环,即平均值过大
}
return 0;
}
int main(){
int i,a,b;
double c,l=-1e7,r=1e7,mid,ans;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++){
scanf("%d%d%lf",&a,&b,&c);
add(a,b,c);
}
while(l+ep<r){
mid=(l+r)/2;
if(check(mid))//判断是否有负环
r=mid-ep,ans=mid;//减小右边界
else
l=mid+ep;//增大左边界
}
printf("%.8lf\n",ans);
return 0;
}