传送门

题解

题意 = 找出无向基环树森林的每颗基环树的直径。

我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无向图环 :

dalao的链接

然鹅大佬的方法有一点小问题, 无法找出只有两个节点的环,改动后代码:

 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 岛屿 - 基环树的更多相关文章

  1. [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)

    [bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...

  2. bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】

    我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...

  3. BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]

    基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...

  4. bzoj 1791: [Ioi2008]Island 岛屿

    #include<iostream> #include<cstdio> #define M 1000009 using namespace std; *M],cnt,n,hea ...

  5. P4381 [IOI2008]Island(基环树+单调队列优化dp)

    P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...

  6. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

  7. [BZOJ1791][IOI2008]Island岛屿(环套树DP)

    同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...

  8. 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)

      1791: [Ioi2008]Island 岛屿  Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 908  Solved: 159 [Su ...

  9. bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿

    http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...

随机推荐

  1. gdufe1534-小小怪一定认真听课-dfs

    Problem Description: 又到了选课的时间啦.大一萌新小小怪下士第一次选课没有制定好高效的策略,导致第一学期的学分不高,他想在第二学期获得尽可能多的学分,因此作为小小怪下士的上司搭档兼 ...

  2. Linux部署项目

    1 安装jdk 第一步:获取Linux系统中jdk安装包和tomcat安装包(后面要用,所以上传两个) 第二步:使用secureCRT客户端工具连到服务器 第三步:使用命令创建一个目录,作为软件的安装 ...

  3. vue watch,computed,metods的区别

    通俗来讲:computed是在HTML DOM加载后马上执行的,如赋值:而methods则必须要有一定的触发条件才能执行,如点击事件:watch呢?它用于观察Vue实例上的数据变动.对应一个对象,键是 ...

  4. javascript中scrollTop和offsetTop的区别

    scrollTop是指某个可滚动区块向下滚动的距离,offsetTop则是元素的上边框与父元素的上边框的绝对距离. 1.offsetTop   : 当前对象到其上级层顶部的距离. 不能对其进行赋值.设 ...

  5. sqlite 时间戳转时间

    ), 'unixepoch','localtime') from messages where data != '' order by timestamp desc 官方eg: Examples Co ...

  6. Spring Boot Maven 打包 Jar

    Maven pom.xml 必须包含 <packaging>jar</packaging> <build> <plugins> <plugin&g ...

  7. Bootstrap的aria-label和aria-labelledby

    [Bootstrap的aria-label和aria-labelledby] 用于盲人阅读的属性,基本也没什么用. 参考:http://blog.csdn.net/liuyan19891230/art ...

  8. PHP ActiveRecord demo栗子中 关于类名 的问题

    问题: ActiveRecord如何将单个类名与表名相关联? 我昨天才发现了ActiveRecord,很奇妙的php数据库框架. 但是,我仍然对以下工作感到困惑: 1.下面这个Person Model ...

  9. 由于html元素加载导致的问题

    js中要求执行的事件是在完全加载完,但由于本地环境测试一直没发现出问题,在上线后由于网络延迟导致元素加载慢,而事件执行完,没达到预期目标. 这时就需要用到属性 readyState readyStat ...

  10. 明明白白你的Linux服务器——日志篇

    日志对于安全来说,非常重要,它记录了系统每天发生的各种各样的事情,你可以通过他来检查错误发生的原因,或者受到攻击时攻击者留下的痕迹.日志主要的功能有:审计和监测.他还可以实时的监测系统状态,监测和追踪 ...