当前位置: 首页 > news >正文

P2656 采蘑菇

题目

P2656 采蘑菇

算法标签: 强连通分量, 缩点, 最长路, 最短路

思路

首先题目中给出的图是有向图, 每次采摘蘑菇之后当前位置的蘑菇数量会减少一定的值, 因此可以先缩点, 将每个联通分量内部的蘑菇都采摘完, 然后再求最长路也就是最大的蘑菇数量

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>using namespace std;const int N = 8e4 + 10, M = 4e5 + 10;int n, m, s;
int head1[N], head2[N], ed[M], ne[M], idx;
int fct[M], w[M];
int dfn[N], low[N], timestamp;
int stk[N], top;
bool in_stk[N];
int scc_cnt, id[N];
int d[N], vals[N];void add(int head[], int u, int v, int val, int weight) {ed[idx] = v, ne[idx] = head[u], fct[idx] = val, w[idx] = weight, head[u] = idx++;
}void tarjan(int u) {dfn[u] = low[u] = ++timestamp;stk[++top] = u;in_stk[u] = true;for (int i = head1[u]; ~i; i = ne[i]) {int v = ed[i];if (!dfn[v]) {tarjan(v);low[u] = min(low[u], low[v]);}else if (in_stk[v]) low[u] = min(low[u], dfn[v]);}if (dfn[u] == low[u]) {++scc_cnt;int ver;do {ver = stk[top--];in_stk[ver] = false;id[ver] = scc_cnt;} while (ver != u);}
}void calc() {for (int u = 1; u <= n; ++u) {for (int i = head1[u]; ~i; i = ne[i]) {int v = ed[i];if (id[u] == id[v]) {int k = w[i];int r = fct[i];while (k > 0) {vals[id[u]] += k;k = k * r / 10;}}}}for (int u = 1; u <= n; ++u) {for (int i = head1[u]; ~i; i = ne[i]) {int v = ed[i];int a = id[u], b = id[v];if (a != b) {add(head2, a, b, 0, w[i]);}}}
}void spfa() {memset(d, -1, sizeof d);queue<int> q;q.push(id[s]);d[id[s]] = vals[id[s]];bool vis[N] = {0};vis[id[s]] = true;while (!q.empty()) {int u = q.front();q.pop();vis[u] = false;for (int i = head2[u]; ~i; i = ne[i]) {int v = ed[i];if (d[u] + w[i] + vals[v] > d[v]) {d[v] = d[u] + w[i] + vals[v];if (!vis[v]) {q.push(v);vis[v] = true;}}}}
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);memset(head1, -1, sizeof head1);memset(head2, -1, sizeof head2);cin >> n >> m;for (int i = 0; i < m; ++i) {int u, v, weight;double val;cin >> u >> v >> weight >> val;add(head1, u, v, (int) (val * 10), weight);}cin >> s;for (int i = 1; i <= n; ++i) {if (!dfn[i]) tarjan(i);}calc();spfa();int ans = 0;for (int i = 1; i <= scc_cnt; ++i) ans = max(ans, d[i]);cout << ans << "\n";return 0;
}

数组模拟队列代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>using namespace std;const int N = 8e4 + 10, M = 4e5 + 10;int n, m, s;
int head1[N], head2[N], ed[M], ne[M], fct[M], w[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
bool in_stk[N];
int scc_cnt, id[N];
int d[N], vals[N];void add(int head[], int u, int v, int factor, int weight) {ed[idx] = v, ne[idx] = head[u], fct[idx] = factor, w[idx] = weight, head[u] = idx++;
}void tarjan(int u) {dfn[u] = low[u] = ++timestamp;stk[++top] = u;in_stk[u] = true;for (int i = head1[u]; ~i; i = ne[i]) {int v = ed[i];if (!dfn[v]) {tarjan(v);low[u]=  min(low[u], low[v]);}else if (in_stk[v]) low[u] = min(low[u], dfn[v]);}if (dfn[u] == low[u]) {++scc_cnt;int v;do {v = stk[top--];in_stk[v] = false;id[v] = scc_cnt;}while (v != u);}
}void calc() {for (int u = 1; u <= n; ++u) {for (int i = head1[u]; ~i; i = ne[i]) {int v = ed[i];int scc1 = id[u], scc2 = id[v];if (scc1 == scc2) {int k = w[i];while (k > 0) {vals[scc1] += k;k = k * fct[i] / 10;}}}}for (int u = 1; u <= n; ++u) {for (int i = head1[u]; ~i; i = ne[i]) {int v = ed[i];int scc1 = id[u], scc2 = id[v];if (scc1 != scc2) add(head2, scc1, scc2, 0, w[i]);}}
}void spfa() {int q[N], h = 0, t = -1;bool vis[N] = {0};int root = id[s];q[++t] = root;vis[root] = true;d[root] = vals[root];while (h <= t) {int u = q[h++];vis[u] = false;for (int i = head2[u]; ~i; i = ne[i]) {int v = ed[i];if (d[u] + w[i] + vals[v] > d[v]) {d[v] = d[u] + w[i] + vals[v];if (!vis[v]) {q[++t] = v;vis[v] = false;}}}}
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);memset(head1, -1, sizeof head1);memset(head2, -1, sizeof head2);cin >> n >> m;for (int i = 0; i < m; ++i) {int u, v, w;double fct;cin >> u >> v >> w >> fct;add(head1, u, v, (int) (fct * 10), w);}cin >> s;for (int i = 1; i <= n; ++i) {if (!dfn[i]) tarjan(i);}calc();spfa();int ans = 0;for (int i = 1; i <= scc_cnt; ++i) ans = max(ans, d[i]);cout << ans << "\n";return 0;
}
http://www.xdnf.cn/news/783847.html

相关文章:

  • Linux总结
  • Redis看门狗机制
  • Halcon光度立体法
  • 相机Camera日志分析之二十四:高通相机Camx 基于预览1帧的process_capture_request三级日志分析详解
  • 矩阵的偏导数
  • 点击启动「高效模式」:大腾智能 CAD 重构研发设计生产力
  • 『React』组件副作用,useEffect讲解
  • KEYSIGHT是德科技 E5063A 18G ENA系列网络分析仪
  • 【python与生活】用 Python 从视频中提取音轨:一个实用脚本的开发与应用
  • 6.RV1126-OPENCV 形态学基础膨胀及腐蚀
  • git stash介绍(临时保存当前工作目录中尚未提交的修改)
  • CentOS Stream 8 Unit network.service not found
  • 【Python进阶】元类编程
  • 本人精通各种语言输出hello world
  • Windows应用-音视频捕获
  • 关于Tabs组件下TabPane使用v-if导致顺序错误以及页面渲染异常的解决方法
  • Linux Maven Install
  • LeetCode第245题_最短单词距离III
  • PDF.js无法显示数字签名
  • ARM GIC V3概述
  • 预览pdf(url格式和blob格式)
  • 【C/C++】初步了解享元模式
  • Linux账号和权限管理
  • ubuntu 20.04挂载固态硬盘
  • 什么是“音节”?——语言构成的节拍单位
  • 【Java Web】7.事务管理AOP
  • 【Spring】Spring哪些源码解决了哪些问题P1
  • WINUI——Magewell视频捕捉开发手记
  • “packageManager“: “pnpm@9.6.0“ 配置如何正确启动项目?
  • Vue-ref 与 props