【做题】apc001_f-XOR Tree——巧妙转化及dp
对树上的路径进行操作是十分难处理的事情。一开始的思路主要针对于\(a_i<=15\)这一特殊性质上。于是考虑了\(a_i<=1\)的情况,然而除了糊出一个适用范围极小的结论外,并没有什么用。
于是我瞄了一眼题解。令每一个点的值为所有与它相邻的边的权值的异或和。那么,我们发现,对于路径上的点,如果它不是端点,那么有两条与它相邻的的边异或上了相同的值,它的值不变;否则,它的值异或上这个值。并且,容易证明所有边权为零与所有点权为零是等价的。这样,各个结点的值都是无关的,树的结构是无意义的。问题转化成了在一个数列中,每次选取两个数异或上一个相同的值,以最少的操作次数使得数列中所有数为零。
然后,我们发现,对于每一次操作,所选取的数的异或和是不变的。假设这个数列是一个\(n\)个节点的图,而每一次操作都是往里面连边,那么最终每一个联通分量内的数异或和为零。并且,对于所有异或和为零的联通分量,一定存在操作次数为其大小减一的方案,即一个个异或过来,这正对应树的边数。那么,我们得到答案就是\(n-\)联通分量数。
那么,我们可以贪心地把所有值为零的结点单独分为一个联通分量,把两个值相同的结点分为一个联通分量。那么,一共就只有15种取值,每种取值最多1个,总状态数是\(2^{15}\)。于是可以状压dp,转移时我们枚举子集就可以了。
时间复杂度\(O(3^{15})\)。
#include <bits/stdc++.h>
using namespace std;
const int TOT = 1 << 15, N = 100010;
int dp[TOT],n,val[N],cnt[16],ans,sta,res[TOT];
int main() {
int a,b,c,tmp;
scanf("%d",&n);
for (int i = 1 ; i < n ; ++ i) {
scanf("%d%d%d",&a,&b,&c);
a++, b++;
val[a] ^= c;
val[b] ^= c;
}
for (int i = 1 ; i <= n ; ++ i)
++ cnt[val[i]];
ans = n;
ans -= cnt[0];
for (int i = 1 ; i <= 15 ; ++ i)
ans -= cnt[i]/2, sta |= (cnt[i]&1) << i >> 1;
for (int i = 0 ; i < TOT ; ++ i) {
tmp = 0;
for (int j = 1 ; j <= 15 ; ++ j)
if ((i >> j-1)&1) tmp ^= j;
res[i] = tmp;
}
for (int i = 1 ; i < TOT ; ++ i) {
for (int j = i ; j ; j = (j-1) & i)
if (!res[j]) dp[i] = max(dp[i],dp[i^j] + 1);
}
ans -= dp[sta];
printf("%d\n",ans);
return 0;
}
小结:这种代码简单但思想巧妙的题目是十分惊艳的,可惜为数不多。
【做题】apc001_f-XOR Tree——巧妙转化及dp的更多相关文章
- 【做题】spoj4060 A game with probability——dp
赛前做题时忽然发现自己概率博弈类dp很弱,心好慌.(获胜概率或最优解期望) 于是就做了这道题,续了特别久. 一开始列dp式子的时候就花了很长时间,首先搞错了两次,然后忘记了根据上一轮dp值直接确定选什 ...
- 【做题】arc070_f-HonestOrUnkind——交互+巧妙思维
做的第一道交互题-- 首先,有解的一个必要条件是\(a>b\).否则,即当\(a<=b\)时,可以有\(a\)个unkind的人假装自己就是那\(a\)个honest的人.(彼此之间都说是 ...
- 【做题】CSA49F - Card Collecting Game——思维&dp
原文链接 https://www.cnblogs.com/cly-none/p/CSA49F.html 题意:Alice和Bob在玩游戏.有\(n\)种卡牌,每种卡牌有\(b_i\)张,保证\(\su ...
- 【做题】TCSRM592 Div1 500 LittleElephantAndPermutationDiv1——计数&dp
题意:定义函数\(f(A,B) = \sum_{i=1}^n \max(A_i,B_i)\),其中\(A\)和\(B\)都是长度为\(n\)的排列.给出\(n\)和\(k\),问有多少对\((A,B) ...
- AtCoder Grand Contest 11~17 做题小记
原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-11-to-20.html UPD(2018-11-16): ...
- AtCoder Grand Contest 1~10 做题小记
原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...
- (转)poj算法做题顺序
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(poj329 ...
- 「AGC035C」 Skolem XOR Tree
「AGC035C」 Skolem XOR Tree 感觉有那么一点点上道了? 首先对于一个 \(n\),若 \(n\equiv 3 \pmod 4\),我们很快能够构造出一个合法解如 \(n,n-1, ...
- LCT做题笔记
最近几天打算认真复习LCT,毕竟以前只会板子.正好也可以学点新的用法,这里就用来写做题笔记吧.这个分类比较混乱,主要看感觉,不一定对: 维护森林的LCT 就是最普通,最一般那种的LCT啦.这类题目往往 ...
随机推荐
- yii2 rules验证规则,ajax验证手机号码是否唯一
<?php namespace frontend\models; use Yii; use yii\base\Model; /** * Signup form */ class SignupFo ...
- 使用函数接口和枚举实现配置式编程(Java与Scala实现)
概述 做报表时,有时需要根据不同的业务生成不同的报表.这样,需要能够动态地配置列字段,并根据列字段来输出对应的报表.使用函数接口结合枚举可以比较优雅地实现配置式编程. 问题描述如下: 假设有对象 St ...
- python 将字节字符串转换成十六进制字符串
想将一个十六进制字符串解码成一个字节字符串或者将一个字节字符串编码成一个十六进制字符串 1)只是简单的解码或编码一个十六进制的原始字符串,可以使用 binascii模块 >>> s ...
- Qt 之 模态、非模态、半模态窗口的介绍及 实现QDialog的exec()方法
一.简述 先简单介绍一下模态与非模态对话框. 模态对话框 简单一点讲就是在弹出模态对话框时,除了该对话框整个应用程序窗口都无法接受用户响应,处于等待状态,直到模态对话框被关闭.这时一般需要点击对话框中 ...
- python sqlite3 数据库操作
python sqlite3 数据库操作 SQLite3是python的内置模块,是一款非常小巧的嵌入式开源数据库软件. 1. 导入Python SQLite数据库模块 import sqlite3 ...
- 案例:配置apache和nginx的SSL加密传输协议
一.SSI解释 SSI是一种类似于ASP的基于服务器的网页制作技术.将内容发送到浏览器之前,可以使用“服务器端包含 (SSI)”指令将文本.图形或应用程序信息包含到网页中.例如,可以使用 SSI 包含 ...
- VisualSVN Server 服务器搭建 和 TortoiseSVN的配置和使用方法
摘自:https://blog.csdn.net/litaoshoujiao/article/details/8526136 一.VisualSVN Server的配置和使用方法[服务器端] 安装好V ...
- 纯Java增删改查
//自己写的一个完整的带增删改查提交重置功能的表单代码.package com.l16.test5;import java.awt.Color;import java.awt.Container;im ...
- kivy中size和pos的使用
kivy中位置和大小属性的使用: -------------------位置---------------------------- 1.pos_hint(‘x-axis-key’:value,’y- ...
- awk中截取IP字段
由于文本的特殊性,IP字段可能并不是在特定的字段中. 借助awk的match()函数进行匹配截取 awk --re-interval '($0 ~ "xxx"){match($0, ...