题解 | Sightseeing-牛客假日团队赛6J题

J-Sightseeing Cows_牛客假日团队赛6

https://ac.nowcoder.com/acm/contest/993/J

题目描述

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;
}


来源:通信男神杨丽斌
全部评论

相关推荐

个人背景:学院二本计科专业&nbsp;大二开始实习个人经历:安克创新&nbsp;、理想汽车、字节跳动碎碎念:我做事只有三分钟热度。看到进了大厂的同学,我会羡慕,也会跟着努力上进;但遇到好看的小说,我又会放下手头的事沉迷其中,之前的坚持也就中断了。我有些自卑,总觉得自己学历和外貌都不够好。之前偶然在网上受到关注,我就喜欢上了上网,因为这里有很多人认可我。但我也很在意别人的评价,偶尔看到嘲讽的言论,会触发我的自卑情绪,让我感到愤怒。有时候我会强硬地回怼,有时候又会懦弱地选择无视。我也有虚荣心。不管是拿到安克、理想还是字节的机会,我在分享的时候都会带着这份心思。我会特意强调自己学历不好,是为了衬托出过程的艰难,以此显得自己更厉害。我知道,人往往会炫耀自己缺少的东西,来掩盖内心的空洞。我总想着走捷径,不太喜欢踏踏实实地做事。找实习的时候,我花了更多时间在研究面试技巧上,而不是提升专业能力。我会反复听面试录音分析技巧,看面试教程学习怎么和不同的面试官沟通,还会每天自言自语练习语言表达,同学都觉得我有点奇怪。我的实习生涯里,侥幸和运气占了很大一部分。我总在想,如果有一天我失去了这份幸运,这些特质可能会让我一蹶不振。ps:&nbsp;很多人会问我学习路线和经验&nbsp;但是就像我上面说的&nbsp;我的实习过程靠的很多是关键节点的运气&nbsp;技术上面我可能不如很多人&nbsp;&nbsp;所以请大家理性求助和理性参考我的回答&nbsp;附上我的投递记录
我的offer在哪里...:从去年看到现在,飞升哥就是榜样
我的求职进度条
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务