1. 程式人生 > >H - Going in Cycle!! (UVA - 11090)

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

false pop r+ cycle esp body post queue n)

- 題目大意

給你一個有向圖,問你定義一個環的平均值為這個環上所有邊的平均值,問你最小的環的平均值是多少。

- 解題思路

先利用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)