《P2656 采蘑菇》

题目描述

小胖和 ZYR 要去 ESQMS 森林采蘑菇。

ESQMS 森林间有 N 个小树丛,M 条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇。小胖和 ZYR 经过某条小径一次,可以采走这条路上所有的蘑菇。由于 ESQMS 森林是一片神奇的沃土,所以一条路上的蘑菇被采过后,又会长出一些新的蘑菇,数量为原来蘑菇的数量乘上这条路的"恢复系数",再下取整。

比如,一条路上有 4 个蘑菇,这条路的"恢复系数"为 0.7,则第一~四次经过这条路径所能采到的蘑菇数量分别为 4,2,1,0。

现在,小胖和 ZYR 从 S 号小树丛出发,求他们最多能采到多少蘑菇。

输入格式

第一行两个整数,N 和 M。

第二行到第 M+1 行,每行四个数,分别表示一条小路的起点,终点,初始蘑菇数,恢复系数。

第 M+2 行,一个整数 S。

输出格式

一行一个整数,表示最多能采到多少蘑菇,保证答案不超过 (231−1)。

输入输出样例

输入 #1复制

复制代码
3 3
1 2 4 0.5
1 3 7 0.1
2 3 4 0.6
1

输出 #1复制

复制代码
8

说明/提示

对于 30% 的数据,N≤7,M≤15

另有 30% 的数据,满足所有"恢复系数"为 0。

对于 100% 的数据,1≤N≤8×104,1≤M≤2×105,0≤恢复系数≤0.8 且最多有一位小数, 1≤S≤N。

代码实现:

复制代码
#include<bits/stdc++.h>
#define MAXN 80005
using namespace std;

struct E{
    int v, w, r;
    E(int _v, int _w, int _r) : v(_v), w(_w), r(_r) {}
};

vector<E> G[MAXN], G2[MAXN];
stack<int> st;
int dfn[MAXN], low[MAXN], scc[MAXN];
int val[MAXN], dis[MAXN];
int cnt, idx;
int n, m, s, ans;

void tarjan(int u) {
    dfn[u] = low[u] = ++idx;
    st.push(u);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i].v;
        if (!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if (!scc[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (low[u] == dfn[u]) {
        cnt++;
        while (1) {
            int v = st.top(); st.pop();
            scc[v] = cnt;
            if (u == v) break;
        }
    }
}

void findscc() {
    cnt = idx = 0;
    for (int i = 1; i <= n; i++)
        if (!dfn[i])
            tarjan(i);
}

void bfs() {
    queue<int> q;
    q.push(s);
    dis[s] = val[s];
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = 0; i < G2[u].size(); i++) {
            int v = G2[u][i].v;
            if (G2[u][i].w + dis[u] + val[v] > dis[v]) {
                dis[v] = G2[u][i].w + dis[u] + val[v];
                q.push(v);
            }
        }
    }
}

int main() {
    cin >> n >> m;
    int u, v, w;
    double r;
    for (int i = 0; i < m; i++) {
        cin >> u >> v >> w >> r;
        G[u].push_back(E(v, w, r * 10.0));
    }
    cin >> s;
    findscc();
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < G[i].size(); j++) {
            int v = G[i][j].v;
            if (scc[i] == scc[v]) {
                int t = G[i][j].w;
                while (t != 0) {
                    val[scc[i]] += t;
                    t = t * G[i][j].r / 10;
                }
            } else {
                G2[scc[i]].push_back(E(scc[v], G[i][j].w, 0));
            }
        }
    }
    s = scc[s];
    bfs();
    for (int i = 1; i <= cnt; i++) ans = max(ans, dis[i]);
    cout << ans << endl;
    return 0;
}
相关推荐
故事和你916 分钟前
sdut-python-实验四-python序列结构(21-27)
大数据·开发语言·数据结构·python·算法
memcpy010 分钟前
LeetCode 1456. 定长子串中元音的最大数目【定长滑窗模板题】中等
算法·leetcode·职场和发展
liuyao_xianhui14 分钟前
优选算法_模拟_提莫攻击_C++
开发语言·c++·算法·动态规划·哈希算法·散列表
玛丽莲茼蒿28 分钟前
LeetCode hot100【相交链表】【简单】
算法·leetcode·职场和发展
罗湖老棍子29 分钟前
They Are Everywhere(Codeforces- P701C)
算法·滑动窗口·codeforce题解
wen__xvn29 分钟前
力扣模拟题刷题
算法·leetcode
bbbb36529 分钟前
算法复杂度与能耗关系的多变量分析研究的技术7
算法
不要秃头的小孩32 分钟前
力扣刷题——111.二叉树的最小深度
数据结构·python·算法·leetcode
wutang0ka43 分钟前
LeeCode HOT 100 104.二叉树的最大深度
算法
散峰而望1 小时前
【基础算法】从入门到实战:递归型枚举与回溯剪枝,暴力搜索的初级优化指南
数据结构·c++·后端·算法·机器学习·github·剪枝