BZOJ 1791: [IOI2008]Island 岛屿 - 基环树
题解
题意 = 找出无向基环树森林的每颗基环树的直径。
我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无向图环 :
然鹅大佬的方法有一点小问题, 无法找出只有两个节点的环,改动后代码:
void dfs(int x, int last) {
dfn[x] = ++sz;
for(int i = head[x]; i; i = e[i].nxt) {
if(i == last ^ ) continue;
int nt = e[i].to;
if(dfn[nt]) {
if(dfn[nt] < dfn[x]) continue;
cur.push_back(x); mk[x] = ;
for(; nt != x; nt = pre[nt]) cur.push_back(nt), mk[nt] = ;
}
else pre[nt] = x, dfs(nt, i);
}
}
加了手工栈后的代码
int lev2; int st_i2[N],st_x2[N],st_y2[N],st_t2[N]; #define i st_i2[lev2]
#define y st_y2[lev2]
#define x st_x2[lev2]
#define nt st_t2[lev2] void dfs(int u, int last) {
lev2 = ;
st_x2[] = u; st_y2[] = last;
start:;
dfn[x] = ++sz;
for(i = head[x]; i; i = e[i].nxt) {
nt = e[i].to;
if(i == ch(y)) continue;
if(dfn[nt]) {
if(dfn[nt] < dfn[x]) continue;
cur.push_back(x); mk[x] = ;
for(; nt != x; nt = pre[nt]) mk[nt] = , cur.push_back(nt);
continue;
}
pre[nt] = x;
st_x2[lev2 + ] = nt;
st_y2[lev2 + ] = i;
lev2++;
goto start;
end:;
}
lev2--;
if(lev2) goto end;
} #undef i
#undef y
#undef x
#undef nt
设tmp 为某棵基环树的直径
tmp可能是某个环上点的子树的直径, 也有可能是环上两个点之间的距离+两个点到子树的最大距离
找出环后, 求出环上的每个点的子树中的直径, 每颗子树的直径中都更新 tmp的最大值。
接着求出从环上每个点到它子树节点的最远距离$d$, tmp的最大值也可能为 $d_i + d_j + dist(i, j)$。
这个式子最大值可以用拆环+单调队列O(N)求出。
然后把tmp 加到最后答案
代码
为什么不加手工栈比加了手工栈慢20倍
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define rd read()
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define per(i,a,b) for(int i = (a); i >= (b); --i)
#define ll long long
#define R register
using namespace std; const int N = 1e6 + 1e5; int n, head[N], tot, dfn[N], pre[N], sz;
int q[N], mk[N], pos[N];
ll ans, d[N], f[N]; vector<int> pt;
vector<ll> len; struct edge {
int nxt, to, val;
}e[N << ]; int read() {
R int X = , p = ; R char c = getchar();
for(; c > '' || c < ''; c = getchar()) if(c == '-') p = -;
for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
return X * p;
} void add(int u, int v, int val) {
e[++tot].to = v;
e[tot].val = val;
e[tot].nxt = head[u];
head[u] = tot;
} int ch(int x) {
return ((x + ) ^ ) - ;
} int lev2; int st_i2[N],st_x2[N],st_y2[N],st_t2[N]; #define i st_i2[lev2]
#define y st_y2[lev2]
#define x st_x2[lev2]
#define nt st_t2[lev2] void dfs(int u, int last) {
lev2 = ;
st_x2[] = u; st_y2[] = last;
start:;
dfn[x] = ++sz;
for(i = head[x]; i; i = e[i].nxt) {
nt = e[i].to;
if(i == ch(y)) continue;
if(dfn[nt]) {
if(dfn[nt] < dfn[x]) continue;
pt.push_back(x); mk[x] = ;
for(; nt != x; nt = pre[nt]) mk[nt] = , pt.push_back(nt);
continue;
}
pre[nt] = x;
st_x2[lev2 + ] = nt;
st_y2[lev2 + ] = i;
lev2++;
goto start;
end:;
}
lev2--;
if(lev2) goto end;
} #undef i
#undef y
#undef x
#undef nt int lev;
int st_x[N], st_y[N], st_i[N], st_t[N]; #define i st_i[lev]
#define x st_x[lev]
#define y st_y[lev]
#define nt st_t[lev] void dfs2(int u, int fa) {
lev = ;
st_x[] = u; st_y[] = fa;
start:;
for(i = head[x]; i; i = e[i].nxt) {
nt = e[i].to;
if(nt == y || mk[nt]) continue;
st_x[lev + ] = nt;
st_y[lev + ] = x;
lev++;
goto start;
end:;
f[x] = max(f[x], f[nt]);
f[x] = max(f[x], d[x] + d[nt] + e[i].val);
d[x] = max(d[x], d[nt] + e[i].val);
}
lev--;
if(lev) goto end;
} #undef i
#undef x
#undef y
#undef nt void work(int x) {
ll tmp = ; int cnt;
pt.clear(); len.clear();
dfs(x, ); cnt = pt.size();
pt.push_back(pt[]);
len.push_back();
for(R int i = ; i < cnt; ++i) {
for(R int k = head[pt[i]]; k; k = e[k].nxt) if(e[k].to == pt[(i + ) % cnt])
len.push_back(e[k].val);
}
for(R int i = ; i < cnt; ++i)
pt.push_back(pt[i]), len.push_back(len[i]); rep(i, , cnt * - ) {
len[i] += len[i - ];
}
rep(i, , cnt - ) dfs2(pt[i], ), tmp = max(tmp, f[pt[i]]);
int l = , r = ;
rep(i, , cnt * - ) {
while(l <= r && i - q[l] >= cnt) l++;
if(l <= r) tmp = max(tmp, d[pt[i]] + d[pt[q[l]]] + len[i] - len[q[l]]);
else tmp = max(tmp, d[pt[i]]);
while(l <= r && d[pt[i]] - len[i] >= d[pt[q[r]]] - len[q[r]]) r--;
q[++r] = i;
}
ans += tmp;
} int main()
{
n = rd;
rep(i, , n) {
int v = rd, val = rd;
add(i, v, val); add(v, i, val);
}
rep(i, , n) if(!dfn[i]) {
work(i);
}
printf("%lld\n", ans);
}
BZOJ 1791: [IOI2008]Island 岛屿 - 基环树的更多相关文章
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】
我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...
- BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...
- bzoj 1791: [Ioi2008]Island 岛屿
#include<iostream> #include<cstdio> #define M 1000009 using namespace std; *M],cnt,n,hea ...
- P4381 [IOI2008]Island(基环树+单调队列优化dp)
P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 908 Solved: 159 [Su ...
- bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿
http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...
随机推荐
- gdufe1534-小小怪一定认真听课-dfs
Problem Description: 又到了选课的时间啦.大一萌新小小怪下士第一次选课没有制定好高效的策略,导致第一学期的学分不高,他想在第二学期获得尽可能多的学分,因此作为小小怪下士的上司搭档兼 ...
- Linux部署项目
1 安装jdk 第一步:获取Linux系统中jdk安装包和tomcat安装包(后面要用,所以上传两个) 第二步:使用secureCRT客户端工具连到服务器 第三步:使用命令创建一个目录,作为软件的安装 ...
- vue watch,computed,metods的区别
通俗来讲:computed是在HTML DOM加载后马上执行的,如赋值:而methods则必须要有一定的触发条件才能执行,如点击事件:watch呢?它用于观察Vue实例上的数据变动.对应一个对象,键是 ...
- javascript中scrollTop和offsetTop的区别
scrollTop是指某个可滚动区块向下滚动的距离,offsetTop则是元素的上边框与父元素的上边框的绝对距离. 1.offsetTop : 当前对象到其上级层顶部的距离. 不能对其进行赋值.设 ...
- sqlite 时间戳转时间
), 'unixepoch','localtime') from messages where data != '' order by timestamp desc 官方eg: Examples Co ...
- Spring Boot Maven 打包 Jar
Maven pom.xml 必须包含 <packaging>jar</packaging> <build> <plugins> <plugin&g ...
- Bootstrap的aria-label和aria-labelledby
[Bootstrap的aria-label和aria-labelledby] 用于盲人阅读的属性,基本也没什么用. 参考:http://blog.csdn.net/liuyan19891230/art ...
- PHP ActiveRecord demo栗子中 关于类名 的问题
问题: ActiveRecord如何将单个类名与表名相关联? 我昨天才发现了ActiveRecord,很奇妙的php数据库框架. 但是,我仍然对以下工作感到困惑: 1.下面这个Person Model ...
- 由于html元素加载导致的问题
js中要求执行的事件是在完全加载完,但由于本地环境测试一直没发现出问题,在上线后由于网络延迟导致元素加载慢,而事件执行完,没达到预期目标. 这时就需要用到属性 readyState readyStat ...
- 明明白白你的Linux服务器——日志篇
日志对于安全来说,非常重要,它记录了系统每天发生的各种各样的事情,你可以通过他来检查错误发生的原因,或者受到攻击时攻击者留下的痕迹.日志主要的功能有:审计和监测.他还可以实时的监测系统状态,监测和追踪 ...