题意:给你一棵树,你选择删掉一条边,再加上一条边(也要保证为树),问最后树上的节点能够两两完美匹配的加删边方案数?

n<=5e5.

标程:

 #include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int read()
{
int x=;char ch=getchar();
while (ch<''||ch>'') ch=getchar();
while (''<=ch&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x;
}
const int N=;
typedef long long ll;
int size[N],n,u,v;
ll ans;
vector<int> vec[N];
struct node{int a[][];}f[N],g[N];
vector<node> pre[N];
void init(node &x){x.a[][]=;x.a[][]=x.a[][]=x.a[][]=;}
node modi(node x,node y)
{
node c;
c.a[][]=x.a[][]*y.a[][];
c.a[][]=x.a[][]*y.a[][]+x.a[][]*y.a[][];
c.a[][]=x.a[][]*y.a[][]+x.a[][]*(y.a[][]+y.a[][]);
c.a[][]=x.a[][]*y.a[][]+x.a[][]*(y.a[][]+y.a[][])+x.a[][]*y.a[][]+x.a[][]*y.a[][];
return c;
}
node merge(node x,node y)
{
node c;
c.a[][]=x.a[][]*y.a[][];
c.a[][]=x.a[][]*y.a[][]+x.a[][]*y.a[][];
c.a[][]=x.a[][]*y.a[][]+x.a[][]*y.a[][];
c.a[][]=x.a[][]*y.a[][]+x.a[][]*y.a[][]+x.a[][]*y.a[][]+x.a[][]*y.a[][];
return c;
}
void dp1(int x,int fa)
{
size[x]=;init(f[x]);
if (fa!=-) vec[x].erase(find(vec[x].begin(),vec[x].end(),fa));//将fa删去,方便前后缀的处理
for (int i=;i<vec[x].size();i++)
{
int v=vec[x][i]; //注意内部定义
dp1(v,x);size[x]+=size[v];
f[x]=modi(f[x],f[v]);
}
}
void dp2(int x,int fa)
{
node cur;init(cur);
if (fa>) pre[x].push_back(modi(cur,g[x]));else pre[x].push_back(cur);
for (int i=;i<vec[x].size();i++)
pre[x].push_back(modi(pre[x].back(),f[vec[x][i]]));
for (int i=vec[x].size()-;i>=;i--)
{
int v=vec[x][i];
g[v]=merge(pre[x][i],cur);cur=modi(cur,f[v]);
dp2(v,x);
}
}
int main()
{
n=read();if (n&) return puts(""),;
for (int i=;i<n;i++) u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
dp1(,-);dp2(,-);
for (int i=;i<=n;i++)
if (f[i].a[][]&&g[i].a[][]) ans+=(ll)size[i]*(n-size[i]);
else ans+=(ll)(f[i].a[][]+f[i].a[][])*(g[i].a[][]+g[i].a[][]);
printf("%lld\n",ans);
return ;
}

易错点:1.转移式子要认真推。

2.注意函数内部定义变量。

3.将fa在vector中删去,方便前后缀寻址的对应。

题解:dp

把一条边删掉,树就分成了两个子树。要么各自匹配(这样怎么连都可以),要么连一条边后边的端点匹配,也就是两个子树在没有连边前各有一个点没有匹配。

f[i][0/1][0/1]表示以i为根的子树,根是否被匹配,子树中是否恰有一个点未被匹配的未匹配点的选法数。

g表示i为根的子树外的部分的答案(以fa[i]为根)。正反dp两遍后统计答案即可。

CF891D Sloth的更多相关文章

  1. sloth——算法工程师标注数据的福音

    一般算法工程师做标注,都要先开发个标注工具,无非下面几个选项: 1.mfc,C#,优点是交互界面友好,开发难度适中,缺点是没法跨平台 2.matlab,优点是可以跨平台,开发难度非常低,缺点是速度慢. ...

  2. Seven Deadly Sins: Gluttony, Greed, Sloth, Wrath, Pride, Lust, and Envy.

    Seven Deadly Sins: Gluttony, Greed, Sloth, Wrath, Pride, Lust, and Envy.七宗罪:暴食.贪婪.懒惰.暴怒.傲慢.色欲.妒忌.

  3. Codeforces 891D - Sloth(换根 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 换根 dp 好题. 为啥没人做/yiw 首先 \(n\) 为奇数时答案显然为 \(0\),证明显然.接下来我们着重探讨 \(n\) 是偶数 ...

  4. Java Script 编码规范【转】

    Java Script 编码规范 以下文档大多来自: Google JavaScript 编码规范指南 Idiomatic 风格 参考规范 ECMAScript 5.1 注解版 EcmaScript ...

  5. pickle序列化

    通过pickle来序列化: # -*- coding: utf-8 -*- import pickle #-------------------序列化--------------------- zoo ...

  6. nullcon HackIM 2016 -- Programming Question 5

    Dont blink your Eyes, you might miss it. But the fatigue and exhaustion rules out any logic, any wil ...

  7. C++ Primer Plus读书笔记

    第五章 循环和关系表达式 1. 2.类别别名: (1)   #define FLOAT_POINTER float * FLOAT_POINTER pa, pb; 预处理器置换将该声明转换成  flo ...

  8. Deep Learning in a Nutshell: History and Training

    Deep Learning in a Nutshell: History and Training This series of blog posts aims to provide an intui ...

  9. javascript 函数式编程

    编程范式 编程范式是一个由思考问题以及实现问题愿景的工具组成的框架.很多现代语言都是聚范式(或者说多重范式): 他们支持很多不同的编程范式,比如面向对象,元程序设计,泛函,面向过程,等等. 函数式编程 ...

随机推荐

  1. CF1265B Beautiful Numbers

    题意 给一个长度为\(n\)的排列\(P\),求对于\(1\) 到 \(n\)中的每个数\(m\),是否能找到一段长度为\(m\)的区间使得区间内的数是一个\(1\)到\(m\)的排列. 输出一个\( ...

  2. iOS开发之3D Touch

    1.简介 3DTouch是在6s之后苹果的一项技术,只能在6s及其以上机型真机运行,Xcode的模拟器是不支持的. Quick Actions(点击icon的快捷方式) Peek&Pop(应用 ...

  3. MongoDB点滴

    0 http://blog.csdn.net/mydeman/article/details/6652387 1 MongoDB 内置连接池,不需要使用额外的连接池驱动 Note: The Mongo ...

  4. CodeForces1249B1/B2-Books Exchange-dfs-一般搜索+记忆化搜索

    一般搜索 注意:一般定义成void Books Exchange (easy version)  CodeForces - 1249B2 The only difference between eas ...

  5. Day 13 : 函数递归,

    从前有有座山,山里有座庙,庙里有个老和尚给小和尚们讲故事,讲的什么呀,讲的是,从前有有座山,山里有座庙,庙里有个老和尚给小和尚们讲故事,讲的什么呀?讲的是?...... 递归:1.一个函数再内部调用了 ...

  6. Linux下core文件调试

    1,ulimit -a查看默认参数 2,ulimit -c 1024 设置core文件大小,如果超过1024个blocks,则不会产生core文件 注:tune2fs -l /dev/sda8 输出分 ...

  7. xml初步,DTD和Schema约束

    XML 可扩展的标记语言(!!!可扩展) 作用 1.存放数据 2.配置文件 语法 文档声明 <?xml version="1.0" encoding="UTF-8& ...

  8. NFS服务器简易安装

    1.服务端 创建挂载目录 # mkdir /data/nfs 安装NFS软件 # yum install nfs-utils -y 添加配置信息 # vim /etc/exports /data/nf ...

  9. Ansible配置及使用

    使用公私钥实现ssh无密码登录 生成公钥和私钥 ssh-keygen -t rsa 公钥相当于锁id_rsa.pub,私钥相当于钥匙id_rsa 借用ssh-copy-id工具实现无密码登录 ssh- ...

  10. JS对象 指定分隔符连接数组元素join() join()方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的。

    指定分隔符连接数组元素join() join()方法用于把数组中的所有元素放入一个字符串.元素是通过指定的分隔符进行分隔的. 语法: arrayObject.join(分隔符) 参数说明: 注意:返回 ...