【Codeforces】894E.Ralph and Mushrooms Tarjan缩点+DP

题意

给定$n$个点$m$条边有向图及边权$w$,第$i$次经过一条边边权为$w-1-2.-..-i$,$w\ge 0$给定起点$s$问从起点出发最多能够得到权和,某条边可重复经过



有向图能够重复经过的边当且仅当成环,所以tarjan缩点成DAG,缩点后每个点内的权值可以通过二分算出,假设最大的$n$使得$w-\frac{n(n+1)}{2}\ge 0$,那么该点值为$(n+1)w-\frac{n(n+1)(n+2)}{6}$,通过对DAG进行dp算出最长路就是答案

代码

#include <bits/stdc++.h>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long LL;
const int N = 1000005;
int n, m, x, y, w, s;
int head[N], nxt[N], to[N], val[N], cnt;
inline void init(){memset(head, -1, sizeof(head)); cnt = 0;}
inline void add(int u, int v, int w) {to[cnt] = v, val[cnt] = w, nxt[cnt] = head[u], head[u] = cnt++;}
int head2[N], nxt2[N], to2[N], cnt2; LL val2[N];
inline void init2() {memset(head2, -1, sizeof(head)); cnt2 = 0;}
inline void add2(int u, int v, LL w) {to2[cnt2] = v, val2[cnt2] = w, nxt2[cnt2] = head2[u], head2[u] = cnt2++;}
int dfs_ind = 1, dfn[N], low[N], sccno[N], scc_cnt = 0;
LL w_[N];
stack<int> st;
void tarjan(int u) {
    dfn[u] = low[u] = dfs_ind++;
    st.push(u);
    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = to[i];
        if(!dfn[v]) {tarjan(v); low[u] = min(low[u], low[v]);}
        else if(!sccno[v]) {low[u] = min(low[u], dfn[v]);}
    }
    if(dfn[u] == low[u]) {
        scc_cnt++;
        while(1) {
            int x = st.top(); st.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
inline LL cal(LL x) {
    LL n = sqrt(2.0 * x + 0.25) - 0.5;
    return (n + 1) * x - (n + 1) * (n + 2) * n / 6;
}
void DAG() {
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(sccno,0,sizeof(sccno));
    memset(w_,0,sizeof(w_));
    init2();
    for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i);
    for(int i = 1; i <= n; ++i) {
        for(int j = head[i]; ~j; j = nxt[j]) {
            int v = to[j];
            if(sccno[i] != sccno[v]) {
                add2(sccno[i], sccno[v], 1LL * val[j]);
            }else w_[sccno[i]] += cal(val[j]);
        }
    }
}
LL dp[N];
void dfs(int u) {
    if(~dp[u]) return;
    dp[u] = w_[u];
    for(int i = head2[u]; ~i; i = nxt2[i]) {
        dfs(to2[i]);
        dp[u] = max(dp[u], w_[u] + dp[to2[i]] + val2[i]);
    }
}
int main() {
    init();
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &x, &y, &w);
        add(x, y, w);
    }
    scanf("%d", &s);
    DAG();
    memset(dp, -1, sizeof(dp));
    dfs(sccno[s]);
    cout << dp[sccno[s]] << endl;
    return 0;
}
时间: 2024-10-10 19:01:40

【Codeforces】894E.Ralph and Mushrooms Tarjan缩点+DP的相关文章

P1073 最优贸易 (tarjan缩点+dp)

题目链接:https://www.luogu.com.cn/problem/P1073. C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 mmm 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 11 1条. CC C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿

NOIP2009最优贸易[spfa变形|tarjan 缩点 DP]

题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息 之后,便决定在旅游的

tarjan缩点与割点

Tarjan算法 先是废话时间:说来挺惭愧 , 好几个月以前就学过tarjan算法然而现在才第一次写 模板题:[luogu P3387][模板]缩点 tarjan缩点&dp 为啥要缩点答案显然 把环缩成一个点 然后图上拓扑dp tarjan同名算法有很多 , 比如本blog的缩点与割点的tarjan算法其实并不是一个东西 , 但是很是相似 这个tarjan , 需要三个东西 第一:一个栈来存放搜到的点 第二:一个时间戳dfn , 表示第几个搜到这个点的 第三:low数组 , 表示够追溯到的最早的

[2019CSP-S赛前训练][CF894E] Ralph and Mushrooms

题目链接:https://www.luogu.org/problem/CF894E 题目大意 Ralph打算去蘑菇森林采蘑菇. 蘑菇森林里有n个蘑菇丛,有m条有向的路连接这些丛林(可能连向自己,也可能两个丛林之间有多条路).经过某条路时,Ralph可以采走这条路上的全部蘑菇.然而,这是一片神奇的蘑菇森林,蘑菇被采走后会重新长出来一些.但是,第k次走过这条路后,这条路上重新长出的蘑菇会比上次少k.(举个栗子,第一次有w个蘑菇,第二次有w-1个蘑菇,第三次有w-1-2个蘑菇,以此类推--)(还有,蘑

【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Status][Discuss] Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti.Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

[BZOJ 1051][HAOI 2006]受欢迎的牛(tarjan缩点)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=1051 唔...这题好像在POJ上见过? 比较水的题,很好想出思路.牛和牛之间的关系就像有向图,牛a喜欢牛b相当于建立有向边a->b,然后在这个有向图中,每个强连通分量里的牛们相当于是相互喜欢的,把这个图缩点成DAG,DAG里如果有且仅有一个出度为0的点,则这个点对应强连通分量里的所有牛都是受欢迎的牛,如果没有出度为0的点,当然就没受欢迎的牛了,如果出度为0的点的个数大于1,则每个出度为0的

tarjan缩点以及链式前向星的基本+应用(洛谷1262 间谍网络)

题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报.所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子.因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报. 我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额.同时我们还知道哪些间谍手中具体掌握了哪些

【BZOJ-2438】杀人游戏 Tarjan + 缩点 + 概率

2438: [中山市选2011]杀人游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1638  Solved: 433[Submit][Status][Discuss] Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌