题目大意:求平均权最小的环
题解:二分+dfs式spfa判负环
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-9
const int M=3005;
int m,n,t;
int head[M];
double z[M*5],d[M];
bool flag,vis[M];
struct edge{int to,nex;double val;}e[M*5];
inline void add(int u,int v){e[t].to=v;e[t].nex=head[u];head[u]=t++;}
void dfs(int x)
{
if(vis[x]) {
throw(true);
}
vis[x]=1;
for(int i=head[x];i!=-1;i=e[i].nex)
{
int v=e[i].to;
if(d[v]>d[x]+e[i].val)
d[v]=d[x]+e[i].val,dfs(v);
}
vis[x]=0;
}
inline bool judge(double x)
{
for(int i=0;i<t;i++)
e[i].val=z[i]-x;
for(int i=1;i<=n;i++)
d[i]=0,vis[i]=0;flag=0;
for(int i=1;i<=n;i++)
{
try {dfs(i);}//奇怪的东西
catch(bool){return true;}
}
return false;
}
void work()
{
double l,r,mid,ans;
l=-INF,r=INF;
while(r-l>=eps)
{
mid=(l+r)/2.0;
if(judge(mid))
ans=mid,r=mid;
else l=mid;
}
printf("%.8lf\n",ans);
}
void init()
{
int x,y;
t=0,memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=1;i<=m;i++){
scanf("%d%d%lf",&x,&y,&z[i-1]);//存边权数组编号从0开始……
add(x,y);
}
}
int main()
{
init();
work();
return 0;
}