码迷,mamicode.com
首页 > 其他好文 > 详细

H - Going in Cycle!! (UVA - 11090)

时间:2018-02-15 20:15:50      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:next   queue   pos   check   判断   一个   利用   while   blog   

- 题目大意

     给你一个有向图,问你定义一个环的平均值为这个环上所有边的平均值,问你最小的环的平均值是多少。

- 解题思路

    先利用spfa来判断负环,然后用二分去判断若当前的二分值是mid,让所有的边都减去这个值,如果此时图中出现负环,则说明有环的平均值比这个更小。

- 代码

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int N=500;
const int M=1e6+5;
const int INF=0x3f3f3f;
int n,m;
struct edge {
    int v,next;
    double w;
}e[M*2];
int head[N], cnt;
double d[N];
int inq[N];
int cn[N];
void init ()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,double c)
{
    e[cnt].w=c;
    e[cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
bool SPFA(int s) {
    memset(d, INF, sizeof(d));
    memset(inq, 0, sizeof(inq));
    memset(cn, 0, sizeof(cn));
    queue<int> Q;
    Q.push(s);
    d[s] = 0;
    inq[s] = 1;
    while(Q.size()) {
        int u = Q.front();
        Q.pop();
        inq[u] = 0;
        for(int i = head[u]; ~i; i = e[i].next)
        {
            int v = e[i].v;
            double w = e[i].w;
            if(d[v] > d[u] + w)
            {
                d[v] = d[u] + w;
                if(!inq[v])
                {
                    Q.push(v);
                    inq[v] = 1;
                    if(++cn[v] >= n)
                        return false;
                }
            }
        }
    }
    return true;
}

bool check(double x)
{
    bool vis=false;
    for(int i=1;i<=n;i++)
    {
        for(int j=head[i];j!=-1;j=e[j].next)
            e[j].w-=x;
    }
    for(int i=1;i<=n;i++)
    {
        if(!SPFA(i))
            vis=true;
    }
     for(int i=1;i<=n;i++)
    {
        for(int j=head[i];j!=-1;j=e[j].next)
            e[j].w+=x;
    }
    return vis;
}

int main()
{
    int t,a,b;
    double c;
    scanf("%d",&t);
    for(int k=1;k<=t;k++)
    {
        double l=INF,r=0,mid;
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lf",&a,&b,&c);
            addedge(a,b,c);
            l=min(l,c);
            r=max(r,c);
        }
        printf("Case #%d: ",k);
        if(!check(r+1))
             printf("No cycle found.\n");
        else
        {
            while(r-l>1e-8)
            {
                mid=(r+l)/2;
                if(check(mid))
                    r=mid;
                else
                    l=mid;
            }
            printf("%.2lf\n",r);
        }
    }
    return 0;
}

  

H - Going in Cycle!! (UVA - 11090)

标签:next   queue   pos   check   判断   一个   利用   while   blog   

原文地址:https://www.cnblogs.com/alpacadh/p/8449749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!