骑士 bzoj-1040 ZJOI-2008

    题目大意:n个骑士,每个骑士有权值val和一个讨厌的骑士。如果一个骑士讨厌另一个骑士那么他们将不会一起出战。问出战的骑士最大atk是多少。

    注释:$1\le n,atk\le 10^6$。

      想法:树形dp的一道好题qwq。大师说是基环树的一道裸题。什么是基环树?就是一个点数条边的连通图,这样的连通图有且只有一个环。证明:挖坑代填。

        那么这道题,首先如果两个骑士A讨厌B,其实和B讨厌A的效果是一样的,所以我们连双向边。那么对于任意的连通块,一定存在一个环,我们取环上不同相连两点x和y,将它们之间的边强行断掉。此时,由于x和y在环上,必定仍是联通的,之前如果两点连通经过x到y的边d,那么可以将那条路径等价到现在x到y的路径。如果两点连通不经过d,无影响。那么现在就是一棵树了,相邻两点不能同时选取,每个点有权值...没有上司的舞会(没有上司的舞会?)啊!然后分别以x和y为根跑树形dp,f[i]表示选i的最大战斗力,g[i]表示不选i的最大战斗力。然后我们明白:由于x和y的边使我们强行断掉的,他们之间其实仍是相连的,所以我们在以x为根的时候钦定y一定不能选;以y为根同理。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
typedef long long ll;
int fa[N];
ll g[N],f[N],val[N];
int to[N<<1],nxt[N<<1],head[N],tot;
int cnt,ra[N],rb[N];
inline void add(int x,int y)//加边
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int find(int x)//并查集
{
return fa[x]==x?x:(fa[x]=find(fa[x]));
}
void dfs(int pos,int fa)//树形dp
{
f[pos]=val[pos];//表示选取pos节点的最大权值
g[pos]=0;//表示选取pos节点的最大权值
for(int i=head[pos];i;i=nxt[i])
{
if(to[i]==fa) continue;
dfs(to[i],pos);
f[pos]+=g[to[i]];
g[pos]+=max(f[to[i]],g[to[i]]);
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
ll ans=0;
for(int b,i=1;i<=n;i++)
{
scanf("%lld%d",&val[i],&b);
if(find(i)!=find(b))
{
add(b,i);add(i,b);
fa[find(b)]=find(i);
}
else
{
ra[++cnt]=i;
rb[cnt]=b;
}
}
ll maxn=0;
for(int i=1;i<=cnt;i++)
{
dfs(ra[i],0),maxn=g[ra[i]];//小技巧,选取x可以钦定x是g,选取y同理,这样和上述题解达到的效果一致
dfs(rb[i],0),maxn=max(maxn,g[rb[i]]);//而且实现简单。
ans+=maxn;
}
printf("%lld\n",ans);
return 0;
}

    小结:错误1.题目中要求的是每一个maxn的综合,我直接输出了... ...

         2.49行有一个小技巧:由于已经路径压缩完毕,所以可以写成fa[fa[b]]=fa[i],省去调用函数的时间。

[bzoj1040][ZJOI2008]骑士_树形dp_基环树_并查集的更多相关文章

  1. 2018.11.06 bzoj1040: [ZJOI2008]骑士(树形dp)

    传送门 由题可知给出的是基环森林. 因此对于每个基环森林找到环断开dpdpdp两次就行了. 代码: #include<bits/stdc++.h> using namespace std; ...

  2. Educational Codeforces Round 51 (Rated for Div. 2) G. Distinctification(线段树合并 + 并查集)

    题意 给出一个长度为 \(n\) 序列 , 每个位置有 \(a_i , b_i\) 两个参数 , \(b_i\) 互不相同 ,你可以进行任意次如下的两种操作 : 若存在 \(j \not = i\) ...

  3. BZOJ4399魔法少女LJJ——线段树合并+并查集

    题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉人的奶浆味: ...

  4. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  5. 【BZOJ2733】永无乡(线段树,并查集)

    [BZOJ2733]永无乡(线段树,并查集) 题面 BZOJ 题解 线段树合并 线段树合并是一个很有趣的姿势 前置技能:动态开点线段树 具体实现:每次合并两棵线段树的时候,假设叫做\(t1,t2\), ...

  6. 洛谷P3402 【模板】可持久化并查集 [主席树,并查集]

    题目传送门 可持久化并查集 n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 ...

  7. 洛谷P4121 [WC2005]双面棋盘(线段树套并查集)

    传送门 先膜一下大佬->这里 据说这题正解是LCT,然而感觉还是线段树套并查集的更容易理解 我们对于行与行之间用线段树维护,每一行内用并查集暴力枚举 每一行内用并查集暴力枚举连通块这个应该容易理 ...

  8. 2019牛客暑期多校训练营(第八场)E:Explorer(LCT裸题 也可用线段树模拟并查集维护连通性)

    题意:给定N,M,然后给出M组信息(u,v,l,r),表示u到v有[l,r]范围的通行证有效.问有多少种通行证可以使得1和N连通. 思路:和bzoj魔法森林有点像,LCT维护最小生成树.  开始和队友 ...

  9. BZOJ1040 [ZJOI2008]骑士 基环树林(环套树) 树形动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题意概括 有n个人,每一个人有一个最恨的人. 并且,每一个人有一个权值. 一个人不可以和他最恨的人同时被选中. 现在请你求出在 ...

随机推荐

  1. Java I/O 的工作机制浅析

    I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 ...

  2. codevs1369 xth 砍树(线段树)

    1369 xth 砍树  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description 在一个凉爽的夏夜,xth 和 rabbi ...

  3. 洛谷P1478 陶陶摘苹果(升级版)

    题目数据范围小,开两个数组手写冒泡应该也能过,不过和之前在牛客上的一题类似用结构体数组就好了,主要是注意用结构体数组的排序 题目 题目描述 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果 ...

  4. go 成长路上的坑(1)

    一.先来看一段代码 package main import "fmt" type X struct{} func (x *X) test(){ println("h1&q ...

  5. Netty--数据通信和心跳检测

    数据通信 概述: netty的ReadTimeOut实现方案3 服务端: public class Server { public static void main(String[] args) th ...

  6. 【Codeforces866E_CF866E】Hex Dyslexia(Structure & DP)

    It's my first time to write a blog in EnglishChinglish, so it may be full of mistakes in grammar. Pr ...

  7. 自动保存草稿 asp+ajax自动存稿功能详解(转自影子)

    自动保存草稿功能的原理 我们都知道网页是一种无状态的,每次都需要请求,响应,当一次请求完成后就与服务器断开连接了,所以我们不能像网页一样实现实时的交互功能,但是为了满足更多的需求一个比较无敌的程序员还 ...

  8. Linux查找目录下的按时间过滤的文件

    在维护项目中,有时会指定都一些条件进行过滤文件,并对该批文件进行操作:这时我们将使用shell命令进行操作:直接上代码 #!/bin/sh #BEGIN #`find ./ ! -name " ...

  9. WinForm窗体项目 之 MySchool管理系统终极版

    学习WinForm窗体程序也有一段时间了,今天就来尝试着来一个项目热热身~ 在我们通常使用的MySchool管理中,不外乎这几种功能:增.删.改.查.改密码 在过去的C#中确实是挺简单的,但是在学习了 ...

  10. OFDM同步算法之Schmidl算法

    Schmidl算法代码 算法原理 训练序列结构 T=[A A],其中A表示复伪随机序列PN,进行N/2点ifft变换得到的符号序列 \[M(d)=\frac{\left | P(d) \right | ...