1720:均值最小环

1720:均值最小环


时间限制: 1000 ms         内存限制: 131072 KB
提交数: 310     通过数: 62

【题目描述】

画一个 n 个节点,m 条边的带权有向图,想从中找出权值的平均值最小的环。有向图中可能不存在环,求最小的平均权值。

【输入】

共 m+1 行。

第$1行,2个整数n和m,表示点数和边数。

第$2 ~ m+1行,每行3个正整数 $u,v,w,表示u与v之间有一条权值为w的有向边。

【输出】

如果输入数据无环,输出“PaPaFish is laying egg!”。(不含引号)

否则输出一个浮点数 ans,表示所有环中,权值的平均值最小的环的平均权值。答案保留2位小数。

【输入样例】

2 2

1 2 2

2 1 3

【输出样例】

2.50

【提示】

【数据规模】

对于前40%的数据 n≤50,m≤5000;

对于100%的数据 $≤n≤1000,1≤m≤10000,0≤w≤10000000

二分答案,dfs判环

```

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
const int N = 1e5 + 10;
int n, m;
int h[N],ne[N],e[N];
double w[N];
double dis[N];
int idx;
bool st[N];
void add(int a,int b,double c)
{
    e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++;
}
bool bj;
double mid;
bool spfa(int t)
{
    st[t] = 1;
    for(int i = h[t]; ~i ; i = ne[i])
    {
        int j = e[i];
        if(dis[j] <= dis[t] + w[i] - mid) continue;
        if(st[j] && dis[t] + w[i] - mid <= 0) return 1;
        dis[j] = dis[t] + w[i] - mid;
        if(!st[j] && spfa(j)) return 1;
    }
    st[t] = 0;
    return 0;
}

bool check(double k)
{
    memset(st,0,sizeof(st));
    memset(dis,0,sizeof(dis));
    for(int i = 1;i <= n; i++)
    {
        if(!dis[i] && spfa(i)) return 1;
    }
    return 0;
}

int main()
{
    scanf("%d %d",&n,&m);
    memset(h, -1,sizeof(h));
    double L = 0, R = 10000000 + 120;
    double ans = -1;
    double eps  = 1e-3;
    for(int i = 1; i <= m; i++)
    {
        int a, b;
        double c;
        scanf("%d %d %lf",&a,&b,&c);
        add(a, b, c);
    }
    while(R - L >= 0.0004)
    {
         mid = (R + L) / 2;
        if(check(mid))
        {
            R = mid;
            ans = mid;
        }
        else L = mid;
    }
    if(ans != -1)
    printf("%.2lf",ans);
    else puts("PaPaFish is laying egg!");
    return 0;
}

```

1720:均值最小环

上一篇:一封手机信牵出的有关诺基亚的种种“内幕”


下一篇:Geogebra指令