bzoj1791
1791: [Ioi2008]Island 岛屿
Time Limit: 20 Sec Memory Limit: 162 MB
Submit: 1680 Solved: 369
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
3 8
7 2
4 2
1 4
1 9
3 4
2 3
Sample Output
HINT
Source
这个图跟信息传递很像,也就是一个基环树,但是我很思博地没看出来。。。
事实上这是一个基环树森林,我们要求的是每棵基环树的直径(不太准确),也就是基环树上最长的路径
首先得找到环,这里我们可以分两种情况
1.这条路径在环上,那么也就是说两个端点在环上某个顶点的子树里或环上,那么这个样子可以这么计算:dis=d子树1+d子树2+d环,我们先把环拉开复制一遍接在后面,然后对于环上每个顶点的子树计算一下子树最深的地方到环上该点的距离,这些子树取个最大值。然后就可以dp了dp[i] = max(dp[i], d[i]-d[j]) 这里可以用单调队列优化,具体看代码
2.最长路径位于环上某个顶点的子树里,或者跨越某个顶点的两颗子树。这里就是一个树形dp,代码里写的不清楚,其实就是求树的直径的代码。
吐槽:写了4个小时,忽略了好几种情况,竟然还会爆栈,我不会写手工栈。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
struct edge {
int nxt, w, to;
} e[N << ];
vector<int> route;
int n, cnt = , pos;
ll ans, Max;
int used[N], vis[N], head[N], mark[N], w[N], prev[N], pree[N << ];
ll mx[N], d[N << ], g[N], q[N], dp[N];
inline int read()
{
int x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x *= ; x += c - ''; c = getchar(); }
return x * f;
}
inline void link(int u, int v, int w)
{
e[++cnt].nxt = head[u];
head[u] = cnt;
e[cnt].to = v;
e[cnt].w = w;
}
void Dp(int u, int last)
{
ll Max1 = , Max2 = ;
for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last)
{
Dp(e[i].to, u);
if(g[e[i].to] + (ll)e[i].w >= Max1)
{
Max2 = Max1;
Max1 = g[e[i].to] + (ll)e[i].w;
}
else if(g[e[i].to] + (ll)e[i].w > Max2) Max2 = g[e[i].to] + (ll)e[i].w;
Max = max(Max, Max1 + Max2);
}
g[u] = Max1;
}
bool getcir(int u, int last)
{
vis[u] = ; bool flag = false;
for(int i = head[u]; i; i = e[i].nxt)
{
if(e[i].to == last && !flag) { flag = true; continue; }
if(!vis[e[i].to])
{
prev[e[i].to] = u; pree[e[i].to] = i;
if(getcir(e[i].to, u)) return true;
}
else { pree[e[i].to] = i; pos = u; prev[e[i].to] = u; return true; }
}
return false;
}
void dfs(int u)
{
used[u] = ;
for(int i = head[u]; i; i = e[i].nxt) if(!used[e[i].to]) dfs(e[i].to);
}
void solve(int u)
{
route.clear();
getcir(u, );
for(int now = pos; !mark[now]; now = prev[now])
{
mark[now] = ;
route.push_back(now); w[now] = e[pree[now]].w;
}
for(int i = ; i < route.size(); ++i)
{
ll Max1 = , Max2 = ;
for(int j = head[route[i]]; j; j = e[j].nxt) if(!mark[e[j].to])
{
Dp(e[j].to, route[i]);
if(g[e[j].to] + (ll)e[j].w >= Max1) { Max2 = Max1; Max1 = g[e[j].to] + e[j].w; }
else if(g[e[j].to] + e[j].w > Max2) Max2 = g[e[j].to] + e[j].w;
mx[route[i]] = max(mx[route[i]], g[e[j].to] + (ll)e[j].w);
dp[route[i]] = max(dp[route[i]], max(Max, Max1 + Max2)); Max = ;
}
}
int lim = route.size(), l = , r = ;
for(int i = ; i < lim; ++i) route.push_back(route[i]);
d[] = q[l] = ;
for(int i = ; i < route.size(); ++i) d[i + ] = d[i] + w[route[i]];
ll delta = mx[route[]] + d[];
for(int i = ; i < route.size(); ++i)
{
while(q[r] - q[l] + >= lim && l <= r) ++l;
if(i) delta = max(delta, mx[route[i]] + d[i] + mx[route[q[l]]] - d[q[l]]);
delta = max(delta, dp[route[i]]);
ll x = mx[route[i]] - d[i];
while(l <= r) if(x > mx[route[q[r]]] - d[q[r]]) --r; else break;
q[++r] = i;
}
ans += delta;
dfs(u);
}
int main()
{
// int size = 50 << 20; // 256MB
// char *p = (char*)malloc(size) + size;
// __asm__("movl %0, %%esp\n" :: "r"(p));
freopen("isl.in", "r", stdin);
freopen("isl.out", "w", stdout);
n = read();
for(int i = ; i <= n; ++i)
{
int u, w; u = read(); w = read();
link(i, u, w); link(u, i, w);
}
for(int i = ; i <= n; ++i) if(!used[i]) solve(i);
printf("%lld\n", ans);
fclose(stdin); fclose(stdout);
return ;
}
bzoj1791的更多相关文章
- 【bzoj1791】岛屿
[bzoj1791]岛屿 题意 求基环树的直径. \(n\leq 100000\) 分析 这道题的题解貌似很少啊. 所以自己也写一份吧. 首先找出基环树的环. 那么树的直径有两种情况: ①以环为根的某 ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- BZOJ1791: [Ioi2008]Island 岛屿
BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...
- BZOJ1791 基环树直径
非递归版4S /************************************************************** Problem: 1791 User: 18357 Lan ...
- [IOI2008/BZOJ1791 岛屿](处理基环树的小技巧&基于bfs树形DP)
IOI2008/BZOJ1791 岛屿 题目大意是在一个基环树森林里求每一棵基环树的直径①的和. 其实就是树的直径的基环树升级版.我们先把环找出来,然后从环上的每一个节点x出发,并且不经过环上其他节点 ...
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 908 Solved: 159 [Su ...
- bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1826 Solved: 405[Submit][S ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- Python之面向对象多态
Python之面向对象多态 多态与多态性: 多态: 多态是指一类事物有多种形态,一个抽象类有多个子类,因而多态的概念依赖于继承. 1.序列类型有多种形态:字符串.列表.元组. 2.动物有多种形态:Pe ...
- CSU1160
十进制-十六进制 Time Limit: 1 Sec Memory Limit: 128 MB Description 把十进制整数转换为十六进制,格式为0x开头,10~15由大写字母A~F表示. ...
- UvaLive 4863 Balloons(贪心)
题意: 给定n个队伍, 然后A房间有a个气球, B房间有b个气球, 然后给出每个队伍所需要的气球数量和到A B房间的距离, 求把气球全部送到每个队伍的最短距离. 分析: 在气球充足的情况下, 那么我们 ...
- codeforces 330b
#include<stdio.h> #include<string.h> #include<stdlib.h> #define N 1100 int map[N]; ...
- [转]MySQL5字符集支持及编码研究
前言 在更新数据库时,有时会遇到这样的错误: Illegal mix of collations (gbk_chinese_ci,IMPLICIT) and (utf8_general_ci,COER ...
- Codeforces 645C Enduring Exodus【二分】
题目链接: http://codeforces.com/contest/645/problem/C 题意: 给定01串,将k头牛和农夫放进, 0表示可以放进,1表示不可放进,求农夫距离其牛的最大距离的 ...
- SOJ 4454 (矩阵快速幂)
先引入数的快速幂 例如计算2的5次方,常规算法2*2*2*2*2,利用快速幂的思想,求出5的二进制表达式101,权值为1和4的位上数字为1,即2^5=2^1*2^4.代码如下,时间复杂度为O(logn ...
- UEFI 下安装 ubuntu 及 win8 双系统 的一些事
给电脑原装的win8系统装Ubuntu 出现了好多问题,重装多次,刷坏一块主板后,(都是泪啊...) 终于成功. 可能的问题 1:win8 系统下进入 blos 解决方案 1)关闭快速启动:管理员命 ...
- codevs——1009 产生数
1009 产生数 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 给出一个 ...
- 安装adt-bundle-windows-x86-20130917时遇到的问题及解决方法
最近在上安卓课,老师让我们下载此软件(adt-bundle-windows-x86-20130917.下载压缩后,打开eclipse的时候,会出现以下情况: 这时说明你的jdk还没下载或者下载错位置了 ...