Description
Input
Output
Sample Input
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
Sample Output
3.66666667
HINT
Source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01分数规划+dfs/SPFA判负环~
根据01分数规划,我们二分寻找能使sum{(a[i]-b[i]*k)*x[i]}==0的k值,然后判负环,如果有负环,就增大k值。
注意这道题卡SPFA判负环,只能用类似于dfs+SPFA的判断方法,详见代码~
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define eps 1e-10
int n,m,x,y,fi[3001],w[20001],ne[20001],cnt;
bool b[3001];
double z,v[20001],ll[20001],mid,dis[3001];
void add(int u,int vv,double val)
{
w[++cnt]=vv;ne[cnt]=fi[u];fi[u]=cnt;v[cnt]=val;
}
bool dfs(int u)
{
b[u]=1;
for(int i=fi[u];i;i=ne[i])
if(dis[w[i]]>ll[i]+dis[u])
{
if(b[w[i]])
{
b[u]=0;return 1;
}
dis[w[i]]=ll[i]+dis[u];
if(dfs(w[i]))
{
b[u]=0;return 1;
}
}
b[u]=0;
return 0;
}
bool che()
{
memset(dis,0,sizeof(dis));
for(int i=1;i<=cnt;i++) ll[i]=v[i]-mid;
for(int i=1;i<=n;i++) if(dfs(i)) return 1;
return 0;
}
int read()
{
int totnum=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {totnum=(totnum<<1)+(totnum<<3)+ch-'0';ch=getchar();}
return totnum*f;
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;i++) x=read(),y=read(),scanf("%lf",&z),add(x,y,z);
double l=-1e7,r=1e7;
while(r-l>=eps)
{
mid=(l+r)*1.0/2.0;
if(che()) r=mid;
else l=mid;
}
printf("%.8lf\n",mid);
return 0;
}