题目描述

Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big city! The cows must decide how best to spend their free time.
Fortunately, they have a detailed city map showing the major landmarks (conveniently numbered 1.. L) and the unidirectional cow paths that join them. Farmer John will drive the cows to a starting landmark of their choice, from which they will walk along the cow paths to a series of other landmarks, ending back at their starting landmark where Farmer John will pick them up and take them back to the farm. Because space in the city is at a premium, the cow paths are very narrow and so travel along each cow path is only allowed in one fixed direction.
While the cows may spend as much time as they like in the city, they do tend to get bored easily. Visiting each new landmark is fun, but walking between them takes time. The cows know the exact fun values for each landmark i.
The cows also know about the cowpaths. Cowpath i connects landmark (in the direction ) and requires time to traverse.
In order to have the best possible day off, the cows want to maximize the average fun value per unit time of their trip. Of course, the landmarks are only fun the first time they are visited; the cows may pass through the landmark more than once, but they do not perceive its fun value again. Furthermore, Farmer John is making the cows visit at least two landmarks, so that they get some exercise during their day off.
Help the cows find the maximum fun value per unit time that they can achieve.

输入描述:

* Line 1: Two space-separated integers: L and P
* Lines 2..L+1: Line i+1 contains a single one integer:
* Lines L+2..L+P+1: Line L+i+1 describes cow path i with three space-separated integers: , and

输出描述:

* Line 1: A single number given to two decimal places (do not perform explicit rounding), the maximum possible average fun per unit time, or 0 if the cows cannot plan any trip at all in accordance with the above rules.

链接:https://ac.nowcoder.com/acm/contest/993/J
来源:牛客网
The trip 1 -> 2 -> 3 -> 5 -> 1 has a total fun value of 60 and a length of 10 units for an average fun per unit time of 6. The trip 2 -> 3 -> 5 -> 2 only has an average fun per unit time of 30/6 = 5, and any trip involving landmark 4 has an average fun per unit time of less than 4.

输入
5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2
输出
6.00
说明
The trip 1 -> 2 -> 3 -> 5 -> 1 has a total fun value of 60 and a length of 10 units for an average fun per unit time of 6. The trip 2 -> 3 -> 5 -> 2 only has an average fun per unit time of 30/6 = 5, and any trip involving landmark 4 has an average fun per unit time of less than 4.

解答

题目大意:给你n个点m条有向边,每个点有一个权值,每个边有一个权值,每次可以任意选择一个点出发,选择一条能回到起点的回路,这样可以获得点的权值的和/边的权值的和,问你这个权值的最大值是多少?
一个很经典的类型题目,具体可以看看刘汝佳蓝书上P333页的UVA11090那个题,也是二分+SPFA判环,因为这类没有固定方向求比值的最值问题,都可以用二分来写。
设可以当前可以得到的值为X,点权为val,边权为w,那么有的值最大,也就是的值最小,而答案肯定是在一个环中的,那么点的个数和边的个数相等。所以我们二分答案,对于每一个取值mid,我们将每个边的权值设置为(注意要改回来),在SPFA中找一个能满足mid当前取值的有环的最短路即可。
#include <cstdio>
#include <iostream>
#include <string.h>
#include <queue>
#include <algorithm>
#include <math.h>
#include <cmath>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
const int maxn=1005,maxk=5005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const db eps = 1e-5;
int head[maxn],t[maxn];
bool inq[maxn];
db a[maxn],d[maxn];
int num;
 
struct Edge {
    int from,to,pre;
    db d;
};
Edge e[maxk*2];
int n, m;
void addedge(int from,int to,db d) {
    e[num].from=from,e[num].to=to,e[num].pre=head[from],e[num].d=d;
    head[from]=num++;
}
 
bool spfa(int n,db mid) {
    queue<int> q;
    mem0(t); mem0(inq);
    for (int i=1;i<=n;i++) d[i]=1e9;
    inq[1] = 1; q.push(1); d[1] = 0;
    while (!q.empty()) {
        int now = q.front(); q.pop();
        inq[now] = 0;
        for (int i = head[now]; i != -1; i = e[i].pre) {
            int to = e[i].to;
            if (d[now] +e[i].d - a[now] < d[to]) {
                d[to] = d[now] + e[i].d - a[now];
                if (!inq[to]) {
                    inq[to] = 1; q.push(to); t[to]++;
                    if (t[to] > n) return true;
                }
            }
        }
    }
    return false;
}
bool test(int n,double x){
    for(int i=0;i<m;i++){
        e[i].d*=x;
    }
    int flag=spfa(n,x);
    for(int i=0;i<m;i++){
        e[i].d/=x;
    }
    return flag;
}
int main() {
    int i, j;
    db l, r, mid, ans;
    num = 0; memset(head, -1, sizeof(head));
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) scanf("%lf", &a[i]);
    int x, y;
    for (i = 1; i <= m; i++) {
        scanf("%d%d%lf", &x, &y, &r);
        addedge(x, y, r);
    }
    l = 0; r = 1e4;
    while (true) {
        mid = (l + r) / 2.0;
        if (test(n,mid)) l = mid; else r = mid;
        if (fabs(r - l) < eps) break;
    }
    printf("%.2lf\n", mid);
    return 0;
}


来源:通信男神杨丽斌