uva 11090 Going in Cycle!!

来源:互联网 发布:2016年中日贸易数据 编辑:程序博客网 时间:2024/05/14 08:09

lrj的思路

用二分猜测mid,如果均值小于mid的话,w1 + w2 + ...... + wk < k * mid。

两边同时减去mid,即: (w1 - mid) + (w2 - mid) + ...... + (wk - mid) < 0

也就是要判断每条边减去一个mid后是否存在负圈。这个用Bellman-Ford很好判断,只要一个点入队超过n次就说明有负圈。

记得距离用double。

#include <iostream>#include<stdio.h>#include<cstring>#include<vector>#include<queue>#define maxn 100#define INF  100000100using namespace std;int n,m;double ans;struct Edge{    int from,to;    double dist;};vector<Edge>edges;vector<int>G[maxn];bool inq[maxn];double d[maxn];int p[maxn];int cnt[maxn];double low,high;void init(){    for(int i = 1; i <= n; i++) G[i].clear();    edges.clear();}void add_edge(int from,int to,int dist){    edges.push_back((Edge)    {        from,to,dist    });    int mm = edges.size();    G[from].push_back(mm - 1);}void back(double mid){    for(int i = 0;i < edges.size();i++) edges[i].dist+=mid;}bool negative(double mid){    for(int i = 0;i < edges.size();i++)     {         edges[i].dist-=mid;     }    queue<int>Q;    memset(inq,0,sizeof inq);    memset(cnt,0,sizeof cnt);    for(int i = 1;i <= n;i++)    {        d[i] = INF;        inq[i] = 1;        Q.push(i);    }    d[1] = 0;    while(!Q.empty())    {        int u = Q.front();        Q.pop();        inq[u] = 0;        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[e.from] + e.dist;                p[e.to] = G[u][i];                if(!inq[e.to])                {                    Q.push(e.to);                    inq[e.to] = 1;                    if(++cnt[e.to] > n) {back(mid);return true;}                }            }        }    }    back(mid);    return false;}int main(){    int t;    scanf("%d",&t);    for(int i = 1; i <= t; i++)    {        printf("Case #%d: ",i);        low = INF;        high = 0;        scanf("%d %d",&n,&m);        init();        for(int j = 1; j <= m; j++)        {            int from,to;            double dist;            scanf("%d %d %lf",&from,&to,&dist);            if(high < dist) {high = dist; ans = dist;}            if(low > dist) low = dist;            add_edge(from,to,dist);        }        //这里记得一定要+1,因为可能存在误差        if(!negative(high + 1)) printf("No cycle found.\n");         else        {            high = high + 1;            while(high - low > 1e-3)            {                double mid = low + (high - low)/2;                if(negative(mid))                {                    ans = min(ans,mid);                    high = mid;                }                else low = mid;            }            printf("%.2lf\n",ans);        }    }    return 0;}

 


0 0