zoukankan      html  css  js  c++  java
  • P4381 [IOI2008]Island

    P4381 [IOI2008]Island

    联赛前做点树论

    题意:给一个基环树森林,求每个联通块的直径和,(nle 10^6)别看人话这么短,原题面看了我5分钟

    对于一颗基环树,我们可以提取环上的点。提取完可以看看有什么性质。

    这题,如果把环上的点拎出来,发现直径可以被划分为两部分计算

    • 经过至多环上一个点的路径
    • 经过至少两个环上点的路径

    对于每个联通快取较大者相加即为答案

    这么分的原因是:第一部分很好算。

    在提取出环上的点之后,只需要跑一遍以它为根的子树的直径即可。注意这里的子树指“只经过至多一个环上点(即它自己)的联通块”。至于如何限制这个联通块,只需要把这个环上的点当作根,判断一下出边是否在环上即可,不在环上才过去。

    由于求了直径,最好选取一种可以顺带求出“子树”内最长链的方法,不如后面还得单独求一遍。

    设“子树”内最长链为 (f_i)

    第二部分有个性质,就是这个路径长度等于 (f_i+f_j+dis_{i,j}) ,其中 (i,j) 是环上两点, (dis_{i,j}) 是它们在环上的距离

    这个距离是个二维数组,处理出来是 (O(n^2)) 的,肯定要化简

    考虑对于环按某一个方向记前缀和 (sum_i) ,顺时针还是逆时针随便

    那么路径长等于 (f_i+f_j+max(sum_j-sum_i,sum_n-(sum_j-sum_i))(j>i))

    带了个 (max) 烦死了,我就在处理这个东西的时候卡了很久,也尝试过其他方法,但是感觉都没有这个优,就接着想这个

    后来想到破环成链就简单了

    把数组倍长,那么直接统计 (f_i+f_j+sum_j-sum_i(j-n<i<j)) 的最大值就行了

    发现这个东西显然可以单调队列搞,每个元素的权值设为 (f_i-sum_i) ,队列维护合法的最大的队首

    注意这里的“合法”仅要求 (j-n<i<j) ,所以对于队列中的元素记个下标即可

    枚举 (i) ,每次取出队首更新最大值就做完了。

    然而一调就是 (40) 分钟。

    细节:

    • 最终答案是“每个联通块‘第一类与第二类最大值’的和”!不要分别取最大值输出!(而且因为数据水,单独输出第二类最大值就有85分,很容易被迷惑)
    • 单调队列一定要判空!不空的时候再更新答案。因为元素有负数。STL虽然慢,但是还是有好处的 ,大部分时间我都在调这个了/ll
    • 要特别注意前缀和减法的边界,因为求出的基环树权值是边权,而我们是通过点去记录的,建议输出一下看看,以此确定边界
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef double db;
    #define x first
    #define y second
    #define sz(v) (int)v.size()
    #define pb(x) push_back(x)
    #define mkp(x,y) make_pair(x,y)
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    	while(isdigit(c))x=x*10+c-'0',c=getchar();
    	return f?x:-x;
    }
    #define N 1000005
    int n, H, T, id[N << 1], valp[N];
    LL val[N << 1], sum[N << 1], Mxd, Mxlen, ans;
    LL f[N], g[N], fa[N], dfn[N], tmr, loop[N], cnt, len[N];
    bool onlp[N];
    struct edge{
    	int nxt, to, val;
    }e[N << 1];
    int head[N], num_edge;
    void addedge(int fr, int to, int val) {
    	++ num_edge;
    	e[num_edge].val = val;
    	e[num_edge].to = to;
    	e[num_edge].nxt = head[fr];
    	head[fr] = num_edge;
    }
    void dfs(int u, int ft){
    	dfn[u] = ++ tmr;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to; if (v == ft) continue;
    		if (dfn[v]) {
    			if (dfn[v] < dfn[u]) continue;
    			loop[++ cnt] = v, onlp[v] = 1, valp[cnt] = e[i].val;
    			while (v != u) loop[++ cnt] = fa[v], onlp[fa[v]] = 1, valp[cnt] = len[v], v = fa[v];
    		}
    		else fa[v] = u, len[v] = e[i].val, dfs(v, u);
    	}
    }
    void getd(int u, int ft) {
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to; if (v == ft || onlp[v]) continue;
    		getd(v, u);
    		if (f[v] + e[i].val > f[u]) g[u] = f[u], f[u] = f[v] + e[i].val;
    		else if (f[v] + e[i].val > g[u]) g[u] = f[v] + e[i].val;
    	}
    	Mxd = max(Mxd, f[u] + g[u]);
    }
    void solve(int rt){
    	Mxd = Mxlen = 0;
    	cnt = 0, dfs(rt, 0);
    	for (int i = 1; i <= cnt; ++ i) getd(loop[i], 0), loop[i + cnt] = loop[i], valp[i + cnt] = valp[i];
    	for (int i = 1; i <= cnt << 1; ++ i) sum[i] = sum[i - 1] + valp[i];
    	H = 1, T = 0;
    	for (int i = 1; i <= cnt << 1; ++ i) {
    		while (H <= T && id[H] <= i - cnt) ++ H;
    		if (H <= T) Mxlen = max(Mxlen, val[H] + f[loop[i]] + sum[i]);
    		LL w = f[loop[i]] - sum[i];
    		while(H <= T && val[T] < w) -- T;
    		++T, val[T] = w, id[T] = i;
    	}
    	ans += max(Mxlen, Mxd);
    }
    signed main() {
    	n = read();
    	for (int i = 1; i <= n; ++ i) {
    		int x = i, y = read(), z = read();
    		addedge(x, y, z), addedge(y, x, z);
    	}
    	for (int i = 1; i <= n; ++ i) if (!dfn[i]) solve(i);
    	printf("%lld
    ", ans);
    	return 0;
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    【ACM-ICPC 2018 南京赛区网络预赛 L】Magical Girl Haze
    【Manthan, Codefest 18 (rated, Div. 1 + Div. 2) C】Equalize
    【Manthan, Codefest 18 (rated, Div. 1 + Div. 2) B】Reach Median
    工作总结二
    学习总结
    快速WCF
    EF+linq的增删改查
    JAVASCRIPT闭包以及原型链
    CSS声明各个浏览器私有属性的命名前缀
    mvc的model验证,ajaxhelper,验证机制语法
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13880256.html
Copyright © 2011-2022 走看看