UVA 11090 Going in Cycle!(BellmanFord+二分)

来源:互联网 发布:体育动漫知乎 编辑:程序博客网 时间:2024/05/29 03:04
自己想的时候只想到强连通缩点的做法,联系不到bellmanford,看了白书之后发现这方法好巧妙。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<queue>using namespace std;const int maxn=50+5;struct edge{    int from,to;    double dist;};struct BellmanFord{    int n,m;    vector<edge> edges;    vector<int> G[maxn];    bool inq[maxn];    double d[maxn];    int p[maxn];    int cnt[maxn];        void init(int n){        this->n=n;        for(int i=0;i<n;i++) G[i].clear();        edges.clear();    }        void addedge(int from,int to,double dist){        edges.push_back(edge{from,to,dist});        m=(int)edges.size();        G[from].push_back(m-1);    }        bool negativeCycle(){        queue<int> q;        memset(inq,0,sizeof(inq));        memset(cnt,0,sizeof(cnt));        for(int i=0;i<n;i++) {d[i]=0;inq[0]=true;q.push(i);}        while(!q.empty()){            int u=q.front();q.pop();            inq[u]=false;            for(int i=0;i<G[u].size();i++){                edge &e=edges[G[u][i]];                if(d[e.to]>d[e.from]+e.dist){                    d[e.to]=d[u]+e.dist;                    p[e.to]=G[u][i];                    if(!inq[e.to]) {q.push(e.to);inq[e.to]=true;if(++cnt[e.to]>n) return true;}                }            }        }        return false;    }};BellmanFord solver;int n,m;bool test(double x){    for(int i=0;i<solver.edges.size();i++)        solver.edges[i].dist-=x;    bool ret=solver.negativeCycle();    for(int i=0;i<solver.edges.size();i++)        solver.edges[i].dist+=x;    return ret;}int main(){    int t,kase=0;;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        solver.init(n);        int u,v,dist,up=0;        for(int i=0;i<m;i++){            scanf("%d%d%d",&u,&v,&dist);            u--;v--;            solver.addedge(u,v,dist);up=max(up,dist);        }        printf("Case #%d: ",++kase);        if(!test(up+1)) printf("No cycle found.\n");        else{            double l=0,r=up;            while(l+1e-3<r){                double mid=(l+r)/2;                if(test(mid)) r=mid;else l=mid;            }            printf("%.2f\n",l);        }            }    return 0;}

0 0
原创粉丝点击