#447 Div2 E

题意

给出一个由有向边构成的图,每条边上有蘑菇,假设有 \(n\) 个蘑菇,那么第一次走过这条边可以获得 \(n\) 个蘑菇,第二次 \(n-1\),第三次 \(n-1-2\),第四次 \(n-1-2-3\),后面类推,直至为 \(0\)。问从选定点出发最多可以获得几个蘑菇。

分析

Tarjan 算法缩点,重新给点标号(缩点),且保证了拓扑排序中靠后的点先标号,对于缩完点后的有向无环图,DP去求最长路。(对于拓扑排序后的序列,根据拓扑排序的性质,可以从后往前DP)

拓扑排序保证了:对于有向边 \(a-b\),\(a\) 一定在 \(b\) 前面。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
struct Edge {
int v, w, nxt;
}e[N];
int head[N], cnt;
void addEdge(int u, int v, int w) {
e[cnt].v = v;
e[cnt].w = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
int n, m, c, nn, vis[N], dfn[N], low[N];
int f[N]; // 被缩成的新点的序号
ll sup[N]; // 这个新点能提供的贡献
stack<int> sta;
vector<int> G[N];
void tarjan(int u) { // 找强连通分量
sta.push(u);
dfn[u] = low[u] = ++c;
vis[u] = 1;
for(int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(vis[v] && low[u] > dfn[v]) {
low[u] = dfn[v];
}
}
if(low[u] == dfn[u]) {
++nn;
while(1) {
int id = sta.top();
G[nn].push_back(id);
f[id] = nn;
sta.pop();
vis[id] = 0;
if(id == u) break;
}
}
}
ll calc(int w) {
int d = sqrt(2 * w);
while(d * d + d > 2 * w) d--;
return 1LL * w * (d + 1) - (1LL * d * (d + 1) * (2 * d + 1) / 6 + d * (d + 1) / 2) / 2;
}
ll dp[N];
int main() {
memset(head, -1, sizeof head);
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
}
nn = n;
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 = e[j].nxt) {
int v = e[j].v;
if(f[i] == f[v]) sup[f[i]] += calc(e[j].w);
}
}
int s;
scanf("%d", &s);
s = f[s];
for(int i = n + 1; i <= nn; i++) {
for(int j = 0; j < G[i].size(); j++) {
int q = G[i][j];
for(int p = head[q]; ~p; p = e[p].nxt) {
int v = e[p].v;
if(f[q] != f[v])
dp[i] = max(dp[i], dp[f[v]] + sup[f[v]] + e[p].w);
}
}
}
cout << sup[s] + dp[s] << endl;
return 0;
}

Codeforces #447 Div2 E的更多相关文章

  1. Codeforces #447 Div2 D

    #447 Div2 D 题意 给一棵完全二叉树,每条边有权值为两点间的距离,每次询问 \(x, h\) ,从结点 \(x\) 出发到某一结点的最短路的距离 \(d\) 如果小于 \(h\) ,则答案加 ...

  2. Codeforces #180 div2 C Parity Game

    // Codeforces #180 div2 C Parity Game // // 这个问题的意思被摄物体没有解释 // // 这个主题是如此的狠一点(对我来说,),不多说了这 // // 解决问 ...

  3. Codeforces #541 (Div2) - E. String Multiplication(动态规划)

    Problem   Codeforces #541 (Div2) - E. String Multiplication Time Limit: 2000 mSec Problem Descriptio ...

  4. Codeforces #541 (Div2) - F. Asya And Kittens(并查集+链表)

    Problem   Codeforces #541 (Div2) - F. Asya And Kittens Time Limit: 2000 mSec Problem Description Inp ...

  5. Codeforces #541 (Div2) - D. Gourmet choice(拓扑排序+并查集)

    Problem   Codeforces #541 (Div2) - D. Gourmet choice Time Limit: 2000 mSec Problem Description Input ...

  6. Codeforces #548 (Div2) - D.Steps to One(概率dp+数论)

    Problem   Codeforces #548 (Div2) - D.Steps to One Time Limit: 2000 mSec Problem Description Input Th ...

  7. 【Codeforces #312 div2 A】Lala Land and Apple Trees

    # [Codeforces #312 div2 A]Lala Land and Apple Trees 首先,此题的大意是在一条坐标轴上,有\(n\)个点,每个点的权值为\(a_{i}\),第一次从原 ...

  8. codeforces 447 A-E div2 补题

    A DZY Loves Hash 水题 #include<iostream> #include<cstdio> #include<cstdlib> #include ...

  9. Codeforces #263 div2 解题报告

    比赛链接:http://codeforces.com/contest/462 这次比赛的时候,刚刚注冊的时候非常想好好的做一下,可是网上喝了个小酒之后.也就迷迷糊糊地看了题目,做了几题.一觉醒来发现r ...

随机推荐

  1. [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流

    poj原题 zoj原题 //注意zoj最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...

  2. [学习笔记]可持久化数据结构——数组、并查集、平衡树、Trie树

    可持久化:支持查询历史版本和在历史版本上修改 可持久化数组 主席树做即可. [模板]可持久化数组(可持久化线段树/平衡树) 可持久化并查集 可持久化并查集 主席树做即可. 要按秩合并.(路径压缩每次建 ...

  3. 【COGS 2434】 暗之链锁 树上差分+LCA

    差分就是把一个值拆成许多差的和如 1 2 4 6 9 那么 把这个东西拆成 1 1 2 2 3 就是了,当然也可以理解为对一个问题分解为多个子问题并对其进行操作来得到原问题的答案. 树上差分就更玄妙了 ...

  4. I/O多路转接-epoll

    By francis_hao    Aug 5,2017   APUE讲多路转接的章节介绍了select.pselect和poll函数.而epoll是linux内核在2.5.44引入的.在glibc ...

  5. oracle的rownum使用

    对于rownum来说它是Oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,且rownum不能以任何表的名称作为前缀. ...

  6. Qt 设置应用程序图标(windows)

    Step 1: 创建  xxx.rc 文件. 将ico图标文件复制到项目根目录下.然后在该目录中新建xxx.rc文件,并输入一行代码: IDI_ICON1 ICON DISCARDABLE " ...

  7. 关于MyBatis的collection集合中只能取到一条数据的问题

    问题:在涉及多表查询的时候,使用collection元素来映射集合属性时,出现了只能查询到一条数据的情况,但用sql语句在数据库中查询会有多条记录. 解决:如果两表联查,主表和明细表的主键都是id的话 ...

  8. 转:mybatis 高级结果映射(http://blog.csdn.net/ilovejava_2010/article/details/8180521)

    高级结果映射 MyBatis的创建基于这样一个思想:数据库并不是您想怎样就怎样的.虽然我们希望所有的数据库遵守第三范式或BCNF(修正的第三范式),但它们不是.如果有一个数据库能够完美映射到所有应用程 ...

  9. [51nod1009]数字1的数量

    解题关键:数位dp,对每一位进行考虑,通过过程得出每一位上1出现的次数 1位数的情况: 在解法二中已经分析过,大于等于1的时候,有1个,小于1就没有. 2位数的情况: N=13,个位数出现的1的次数为 ...

  10. SCC模板

    vector<int> G[maxn]; int pre[maxn], low[maxn], c[maxn]; int n, m; stack<int> s; int dfst ...