BZOJ 1486: [HNOI2009]最小圈 [01分数规划]

裸题...平均权值最小的环....

注意$dfs-spfa$时$dfs(cl)$...不要写成$dfs(u)$

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int N=3005,M=1e4+5;
const double eps=1e-9;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int n,m,u,v;
double w;
struct edge{
    int v,ne;
    double w;
}e[M];
int h[N],cnt=0;
inline void ins(int u,int v,double w){
    cnt++;
    e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
}
double d[N],g;
int vis[N],cl;
bool dfs(int u){
    vis[u]=cl;
    for(int i=h[u];i;i=e[i].ne){
        int v=e[i].v;double w=e[i].w-g;
        if(d[v]>d[u]+w){
            d[v]=d[u]+w;
            if(vis[u]==vis[v]) return true;
            else if(dfs(v)) return true;
        }
    }
    vis[u]=0;
    return false;
}
bool NegativeCircle(double mid){
    g=mid;
    memset(vis,0,sizeof(vis));
    memset(d,0,sizeof(d));
    for(cl=1;cl<=n;cl++) if(dfs(cl)) return true;
    return false;
}
bool check(double mid){return NegativeCircle(mid);}
void solve(){
    double l=-1e7,r=1e7;
    while(r-l>eps){
        double mid=(l+r)/2.0;
        if(check(mid)) r=mid;
        else l=mid;
    }
    printf("%.8lf",l);
}
int main(){
    freopen("in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=m;i++){
        u=read(),v=read();
        scanf("%lf",&w);
        ins(u,v,w);
    }
    solve();
}
原文地址:https://www.cnblogs.com/candy99/p/6433815.html