【题目大意】

有n个岛屿,第i个岛屿有有向发射站到第$p_i$个岛屿,改变到任意其他岛屿需要花费$c_i$的代价,求使得所有岛屿直接或间接联通的最小代价。

$1 \leq n \leq 10^5, 1 \leq p_i,c_i \leq 10^9$

【题解】

显然最后是个大环,特判原来就是大环的情况。

考虑每个连通块最多保留多少。

树的答案可以直接dp做出来。

环的答案,根据树的答案dp出来。

h[x][0/1]表示当前做到环上第i个点,环是否被切断了,的最大保留价值。

因为环必须被切断一次。所以最后返回h[r.size()][1]即可。

为了方便代码写的是从后向前(不会涉及到初值特判问题)

懒得写tarjan,写的是和昨天”学外语“一样的找环方法。。

# include <vector>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; const int N = 1e5 + , M = 2e5 + ;
const ll inf = 1e18; vector<int> ring[N]; int rn = ;
int n, p[M], c[M]; int head[N], nxt[M], to[M], tot = , deg[N];
inline void add(int u, int v) {
// cout << u << "-->" << v << endl;
++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}
inline void adde(int u, int v) {
add(u, v), add(v, u);
} namespace SOLVE_RINGS {
struct us {
int fa[N], n;
inline void set(int _n) {
n = _n; for (int i=; i<=n; ++i) fa[i] = i;
}
inline int getf(int x) {
return fa[x] == x ? x : fa[x] = getf(fa[x]);
}
inline void un(int fu, int fv) {
fa[fu] = fv;
}
}U;
bool inrings[N];
int c[N], cn = ;
bool vis[N];
inline void dfs_rings(int x) {
if(vis[x]) {
++rn; for (int i=cn; i; --i) ring[rn].push_back(c[i]);
return ;
}
c[++cn] = x; vis[x] = ;
for (int i=head[x]; i; i=nxt[i]) ++deg[x], dfs_rings(to[i]);
--cn;
} inline void find_rings() {
U.set(n);
for (int i=; i<=n; ++i) {
int fu = U.getf(p[i]), fv = U.getf(i);
if(fu == fv) inrings[i] = ;
else U.un(fu, fv);
}
for (int i=; i<=n; ++i) {
if(!inrings[i]) continue;
cn = ;
dfs_rings(i);
}
} inline void debug_rings() {
for (int i=; i<=rn; ++i) {
printf("num = %d\n ", i);
for (int j=; j<ring[i].size(); ++j)
cout << ring[i][j] << ' ';
cout << endl;
}
} inline void clear_rings() {
for (int i=; i<=rn; ++i) ring[i].clear();
for (int i=; i<=n; ++i) inrings[i] = vis[i] = deg[i] = ;
rn = ;
}
} ll f[N], g[N], h[N][]; inline void dfs_trees(int x, int fa) {
ll mx = ;
for (int i=head[x]; i; i=nxt[i]) {
if(to[i] == fa) continue;
dfs_trees(to[i], x);
mx = max(mx, (ll)c[to[i]]);
f[x] += f[to[i]];
}
g[x] = f[x];
f[x] += mx;
} inline ll solve(vector<int> r) {
ll mx = , s = , res = ;
for (int i=; i<r.size(); ++i) {
int pr = r[(i - + r.size()) % r.size()], nx = r[(i + ) % r.size()];
dfs_trees(r[i], pr);
}
h[r.size()][] = -inf;
h[r.size()][] = ;
for (int i=r.size() - ; ~i; --i) {
int pr = r[(i - + r.size()) % r.size()];
h[i][] = h[i+][] + max(g[r[i]] + c[pr], f[r[i]]);
h[i][] = max(h[i][], h[i+][] + f[r[i]]);
h[i][] = h[i+][] + g[r[i]] + c[pr];
}
return h[][];
} int main() {
// freopen("telegraph.in", "r", stdin);
// freopen("telegraph.out", "w", stdout);
cin >> n;
for (int i=; i<=n; ++i) {
scanf("%d%d", p+i, c+i);
add(p[i], i);
}
SOLVE_RINGS :: find_rings();
if(rn == && ring[rn].size() == n) {
puts("");
return ;
}
// SOLVE_RINGS :: debug_rings();
ll ans = , sum = ;
for (int i=; i<=rn; ++i) ans += solve(ring[i]);
for (int i=; i<=n; ++i) sum += c[i];
cout << sum - ans;
return ;
}

「6月雅礼集训 2017 Day7」电报的更多相关文章

  1. 「6月雅礼集训 2017 Day7」三明治

    [题目大意] $1 \leq n,m \leq 400$ N字形表示:上图第1行第1个那种:Z字形表示上图第1行第2个那种. [题解] 很容易得到结论: 考虑如果紫色比绿色先消去,那么黄色一定会比对应 ...

  2. 「6月雅礼集训 2017 Day7」回转寿司

    [题目大意] 给一个n个数的序列,q次操作,每次选择区间$[l,r]$,给出数p,对于区间$[l,r]$的每个数$x$,做如下操作: 如果$x > p$,就交换$x$和$p$.求每次操作后$p$ ...

  3. 「6月雅礼集训 2017 Day10」quote

    [题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. ...

  4. 「6月雅礼集训 2017 Day4」qyh(bzoj2687 交与并)

    原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2687 [题目大意] 给出若干区间,求一个区间的大于等于2的子集,使得 |区间并| 和 | ...

  5. 「6月雅礼集训 2017 Day11」delight

    [题目大意] 有$n$天,每天能吃饭.睡觉.什么事也不干 每天吃饭的愉悦值为$e_i$,睡觉的愉悦值为$s_i$,什么都不干愉悦值为0. 要求每连续$k$天都要有至少$E$天吃饭,$S$天睡觉. 求最 ...

  6. 「6月雅礼集训 2017 Day11」jump

    [题目大意] 有$n$个位置,每个位置有一个数$x_i$,代表从$i$经过1步可以到达的点在$[\max(1, i-x_i), \min(i+x_i, n)]$中. 定义$(i,j)$的距离表示从$i ...

  7. 「6月雅礼集训 2017 Day11」tree

    [题目大意] 给出一棵带权树,有两类点,一类黑点,一类白点. 求切断黑点和白点间路径的最小代价. $n \leq 10^5$ [题解] 直接最小割能过..但是树形dp明显更好写 设$f_{x,0/1/ ...

  8. 「6月雅礼集训 2017 Day10」perm(CodeForces 698F)

    [题目大意] 给出一个$n$个数的序列$\{a_n\}$,其中有些地方的数为0,要求你把这个序列填成一个1到$n$的排列,使得: $(a_i, a_j) = 1$,当且仅当$(i, j) = 1$.多 ...

  9. 「6月雅礼集训 2017 Day8」route

    [题目大意] 给出平面上$n$个点,求一条连接$n$个点的不相交的路径,使得转换的方向符合所给长度为$n-2$的字符串. $n \leq 5000$ [题解] 考虑取凸包上一点,然后如果下一个是‘R' ...

随机推荐

  1. DAY2敏捷冲刺

    站立式会议 工作安排 (1)服务器配置 (2)数据库连接 (3)页面创意 燃尽图 代码提交记录 感想 林一心:centos配置服务器真的算是一个不小的坑,目前数据库配置清楚,脚本部署好明天测试交互,还 ...

  2. iOS- 用UICollectionViewController 来进行横竖屏九宫格布局

    1.简单说说UICollectionViewController 我们在做九宫格布局时,可以使用UIScrollView,也可以使用UICollectionViewController. 当我们用UI ...

  3. iOS开发多线程编程2 - NSOperation

    1.简介 NSOperation实例封装了需要执行的操作和执行操作所需的数据,并且能够以并发或非并发的方式执行这个操作. NSOperation本身是抽象基类,因此必须使用它的子类,使用NSOpera ...

  4. 3ds max启动慢怎么办?

      有时候启动3ds max的时候一直卡在启动界面进不去怎么办?   在百度上搜到了下面这个解决方案,试了下还真有用:   具体就是进到这个文件夹,然后分别进入第一个和第三个文件夹删掉autodesk ...

  5. PowerMock用法[转]

    转:http://agiledon.github.io/blog/2013/11/21/play-trick-with-powermock/ 当我们面对一个遗留系统时,常见的问题是没有测试.正如Mic ...

  6. STL--heap概述:make_heap,sort_heap,pop_heap,push_heap

    heap并不属于STL容器组件,它分为 max heap 和min heap,在缺省情况下,max-heap是优先队列(priority queue)的底层实现机制. 而这个实现机制中的max-hea ...

  7. anaconda安装不存在的包

    Anaconda作为一个工具包集成管理工具,下载python工具包是很方便的,直接敲: conda install package_name 1 但是有时候安装一个工具包(如skimage)的时候,在 ...

  8. jquery计算器(改良版)

    代码: <!Doctype html> <html> <meta charset="UTF-8"> <title>计算器</t ...

  9. delphi dbgrid 批量保存

    unit uzcdbadd; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo ...

  10. Bootstrap 字体图标、下拉菜单、按钮组

    Bootstrap 字体图标(Glyphicons) 需要引入fonts文件夹中的文件,而且该文件夹必须命名为fonts,然后引进css文件,jQuery文件,以及bootstrap的js文件. 用法 ...