题意:给出一个n个点n条边的图且不一定连通(原题面为每个节点出度为1),相邻节点不能同时被选,每个节点有其对应价值,求最多能获得多少价值?n<=1e6,val[i]<=1e6

分析:很容易想到,如果这个图是n个点n-1条边而且连通的话,那么这个图肯定是一棵树,这用树形dp是很好实现的

dp[x][0]表示x节点不选,其子树(包括x)能产生的最大价值

dp[x][1]表达x节点选,其子树(包括x)能产生的最大价值

那么dp[x][0]+=max(dp[v][1],dp[v][0])

dp[x][1]+=dp[v][0],其中v是x的儿子

那么如果这个题是n个点n条边而且连通的话,那么这个图不就是一棵树再连上一条边,显然会是该图上得到一个环

看到环,我们之前的第一反应肯定是要缩点,但在这题中我们需要做的是将该图转化成树,也就是在环上任意位置断一条边(把这个思路积累下来吧,以前估计没做过类似做法的题)

首先在换上任意断一条边显然是不会使图不连通的,因为断开位置的两个端点依然可以利用环的剩余部分连接

那么再考虑这题的性质,设这两个断开位置的点为a,b

显然,选a的时候是不能选b的,选b的时候是不能选a的

我们在断开这条边的时候,这两个点的关系在树的意义上已经不相连了,也就是说上面那条性质也就无法实现了

所以我们必须要手动实现那条性质,

实现的方法有很多,比较朴素的就是dp[x][0/1]变成dp[x][0/1][0/1][0/1]后面两个0/1分别表示ab两点是否被选,这显然是可以做的,不过略有些复杂

可以考虑我们树中最有标志性的点或者是最易辨识的点显然是根节点

如果我们将a或b设为根节点是不是会更容易计算

注意这里设为根节点并不意味着a,b会被选

假如我们不别的限制,单纯用a为根得到完整的dp数组

显然dp[a][0]表示a不选而b可选可不选,a的子树及其自身的最大价值

dp[a][1]表示a选而b可选可不选,a的子树及其自身的最大价值

显然第二种是可能有违反那条性质的情况存在的(a选b也选),所以dp[a][1]其实对答案没啥帮助

而dp[a][0]又不能包含所有情况(他只包含a不选的情况,没有a选的情况)

所以我们需要再以b为根节点计算dp值

同理dp[b][1]是要舍掉的,

如果将ab选不选表示为0/1 0/1的话

dp[a][0]就是00和01

dp[b][0]就是00和10

而我们所需要的值是00,01和10中的最大值

这里00被计算两遍没啥影响

所以答案就是max(dp[a][0],dp[b][0])注意,这里a和b分别是以a,b为根的结果需要分开求

再回到该题上

这个图不一定连通啊

所以可能有多个这样的图(树+一条边),

那有没有可能出现树+两条边或者树呢?

不可能,因为不要光看这是一个n个点n条边的图

原题上每个节点的出度是1

也就是说,对于任意一个连通子图,他一定有节点个数条边,也就是我们说的树+一条边结构

如果出现树或树+两条边的话,显然则会出现n个点n-1条边的连通子图或者n个点n+1条边的连通子图,这就与题意不符了

所以我们需要对于每个树+一条边的结构干上述过程,然后把每个max加起来

还有我这里断边采用的是重新建图,一开始我写了个判断,但一直wa,你们也可以写写试试,教一下我这个ljQAQ

记得开longlong

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; #define ll long long const int maxn=1e6+; struct Node
{
int to,next;
}e[maxn<<],e2[maxn<<];
int val[maxn];
int head[maxn];
bool vis[maxn];
int head2[maxn];
ll dp[maxn][];
int sb[],cnt,cnt2; void add(int x,int y)
{
e[++cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt;
} void add2(int x,int y)
{
e2[++cnt2].to=y;
e2[cnt2].next=head2[x];
head2[x]=cnt2;
} void find_sb(int x,int fa)
{
vis[x]=;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa)
{
if(vis[v])
{
sb[]=x,sb[]=v;
continue;
}
add2(v,x);add2(x,v);
find_sb(v,x);
}
}
} void dfs(int x,int fa)
{
dp[x][]=(ll)val[x];dp[x][]=0ll;
for(int i=head2[x];i;i=e2[i].next)
{
int v=e2[i].to;
if(v!=fa)
{
dfs(v,x);
dp[x][]+=max(dp[v][],dp[v][]);
dp[x][]+=dp[v][];
} }
} int main()
{
int n,x;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d%d",&val[i],&x);
add(x,i),add(i,x);
}
ll ans=;
for(int i=;i<=n;i++)
{
if(!vis[i])
{
sb[]=sb[]=;find_sb(i,-);
dfs(sb[],-);ll now=dp[sb[]][];
dfs(sb[],-);ans+=max(now,dp[sb[]][]);
}
}
printf("%lld",ans);
return ;
}

题目分享Y的更多相关文章

  1. 题目分享E 二代目

    题意:一棵点数为n的树,每个节点有点权,要求在树中中找到一个最小的x,使得存在一个点满足max(该点点权,该点相邻的点的点权+1,其他点的点权+2)=x 分析:首先要能把题目转化为上述题意 首先题目让 ...

  2. 题目分享D 二代目

    题意:给定一个T条边的无向图,求S到E恰好经过N条边的最短路径 T≤100 N≤1000000 分析:(据说好像假期学长讲过) 首先很容易想到的是dp[i][j][k]表示从i到j经过k条边的最短路径 ...

  3. 题目分享X

    题意:一张票有n位数,如果这张票的前一半数字的和等于后一半数字的和(n一定是偶数),就称这张票为快乐票.有些数被擦除了,标记为’?’(’?‘的个数也是偶数),现在Monocarp 和 Bicarp 进 ...

  4. 题目分享V

    题意:现在两个人做游戏,每个人刚开始都是数字1,谁赢了就能乘以k^2,输的乘以k(k可以是任意整数,每次不一定相同)现在给你最终这两个人的得分,让你判断是否有这个可能,有可能的话Yes,否则No. 分 ...

  5. 题目分享T

    题意:蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n),并保证所有的长度都是非负整数(即:可 能存在长度为0的蚯蚓).每一秒,神刀手会 ...

  6. 题目分享P

    题意: 给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下来从女生开始,双方轮流进行 操作.当一方操作时,他们需要先选择一个不为根的 ...

  7. 2019年腾讯PHP程序员面试题目分享

    有需要学习交流的友人请加入交流群的咱们一起,有问题一起交流,一起进步!前提是你是学技术的.感谢阅读! 点此加入该群​jq.qq.com 1. php 的垃圾回收机制 PHP 可以自动进行内存管理,清除 ...

  8. 20190924-LeetCode解数独题目分享

    解决数独 题目描述 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以 ...

  9. 题目分享H 二代目

    题意:有m个限制,每个限制l1,r1,l2,r2四个数,限制了一个长度为n的数第l1到r1位要与第l2到r2相同,保证r1-l1=r2-l2,求在限制下一共有多少种数 分析: 暴力的话肯定是从l1-r ...

随机推荐

  1. MySQL学习之路7-索引、事务、函数、存储过程、游标

    索引 使用索引快速定位某列中特定值的行,不需要遍历数据表所有行. 创建索引的数据结构:BTREE and HASH. 主键也是一种索引,Primary key. show index from ord ...

  2. C语言变长数组

    #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Variable ...

  3. jvm入门及理解(三)——运行时数据区(程序计数器+本地方法栈)

    一.内存与线程 内存: 内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行.JVM内存布局规定了JAVA在运行过程中内存申请.分配.管理的策略,保证了JVM的 ...

  4. BaseRuntimeException自定义业务异常类实现

    public class BaseRuntimeException extends RuntimeException { private final int code; public BaseRunt ...

  5. BAT脚本编写要点_特殊字符

    BAT脚本编写要点(1)_特殊字符 分类: 其他 2011-03-20 00:58 5621人阅读 评论(0) 收藏 举报 脚本cdatecmdtreesystem 1. 点 与echo连用,作用是换 ...

  6. x聊之后,又一波新的诈骗套路

    前些天刚看到,x聊勒索诈骗套路,骗子的套路可以说是花样百出,这不又一网友深受其害. 事情经过是这样的 某被骗网友由于工资微薄一直想找副业增加收入,关注和加了很多群. 注意群里都是有偏亮头像的”小姐姐” ...

  7. Python实战---制作专属有声小说(调用百度语音合成接口)

    这一次的目标是使用百度云的人工智能接口,实现文字转语音的实时转换,将小说文字转换成语音朗读出来. 百度云接口调用 百度的这个接口对于我们普通用户非常友好,他的很多功能都是免费的,而且我们每天可以免费调 ...

  8. HPU第一次团队赛

    D. Tom的战力问题 Tom被斯派克揍了TAT.Tom下定决心要战胜斯派克.但是在战胜最强的斯派克之前,Tom要先打败其他的狗.为此,他打算先收集一下信息.现在Tom在了得到了一些关于战斗力的小道消 ...

  9. Linux相关操作

    ssh配置秘钥 连接远程服务器时:需要用户持有“公钥/私钥对”,远程服务器持有公钥,本地持有私钥. 客户端向服务器发出请求.服务器收到请求之后,先在用户的主目录下找到该用户的公钥,然后对比用户发送过来 ...

  10. 一、搭建SpringBoot2.0.0M4基础Web项目

    本次开发环境为: 系统:Linux Mint 18 JDK:1.8 开发工具:IntelliJ IDEA 2017.2.4 1.启动IDEA工具,开始创建一个基础项目.点击Create New Pro ...