UVA11090 Going in Cycle!! [spfa负环]

https://vjudge.net/problem/UVA-11090

平均权值最小的回路


为后面的做个铺垫

二分最小值,每条边权减去他,有负环说明有的回路平均权值小于他

spfa求负环的时候可以先把所有点加到队列里,d[i]=0

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=55;
const double eps=1e-3,INF=1e9;
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[N*N];
int h[N],cnt=0;
inline void ins(int u,int v,int w){
    cnt++;
    e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
}
double d[N];
int q[N],head,tail,inq[N],num[N];
inline void lop(int &x){if(x==N) x=1;}
bool spfanc(double mid){
    for(int i=1;i<=n;i++) d[i]=INF;
    head=tail=0;
    memset(inq,0,sizeof(inq));
    memset(num,0,sizeof(num));
    for(int i=1;i<=n;i++) d[i]=0.0,inq[i]=1,q[tail++]=i;
    while(head!=tail){
        int u=q[head++];inq[u]=0;lop(head);
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;double w=e[i].w-mid;
            if(d[v]>d[u]+w){
                d[v]=d[u]+w;
                if(!inq[v]){
                    inq[v]=1,q[tail++]=v,lop(tail);
                    if(++num[v]>n) return true;
                }
            }
        }
    }
    return false;
}
int main(){
    int T=read(),cas=0;
    while(T--){
        printf("Case #%d: ",++cas);
        n=read();m=read();
        cnt=0;memset(h,0,sizeof(h));
        double l=0,r=0;
        for(int i=1;i<=m;i++) u=read(),v=read(),w=read(),ins(u,v,w),r=max(r,w);
        if(!spfanc(r+1)) puts("No cycle found.");
        else{
            while(r-l>eps){
                double mid=(l+r)/2;
                if(spfanc(mid)) r=mid;
                else l=mid;
            }
            printf("%.2f
",l);
        }
    }
}
原文地址:https://www.cnblogs.com/candy99/p/6192426.html