题解 w
一直觉得有点后效性什么的,也不知道怎么写
这题什么时候再康一遍,第一次见这个样子的树形DP,是个树上带不定权边的DP(???
这里能树形DP的原因好像是在这里所有子节点的状态都能表示出来
还有这里最小翻转数量可以转化为每个点翻转边的度数就挺神奇的,可以直接处理掉那几个麻烦的分类讨论
这题成链的部分分和\(d \neq 2\)的部分分其实很好做……后一个dp都不用取max,只有一种可能
全分建议再去康一眼题解
可以发现对于一个点u,如果它有一条d=2的边连到一个点v
不管这条边是否翻转,v的子树中度数为奇的点数量还有路径长度都是要原样传上来的
所以其实这条边选不选只影响u,v度数的奇偶性
而对v的影响其实即为其父节点与它是否连边,这个在设计状态的时候已经考虑进去了
所以只需要开两个二元组分别记录这个点连出的边数是奇数还是偶数时的最小值就行了
随时默念「奇加奇等于偶,偶加奇等于奇」能避免很多智障错误……
细节极多,写了5个小时……
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int head[N], size, cnt[N];
struct edge{int to, next, val;}e[N<<1];
inline void add(int s, int t, int w) {edge* k=&e[++size]; k->to=t; k->val=w; k->next=head[s]; head[s]=size;}
namespace force{
bool vis[N], cge[N], mer[N], len;
void dfs(int u, int fa) {
//cout<<"dfs "<<u<<' '<<fa<<endl;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
dfs(v, u);
if (e[i].val==1) {
if (vis[v]) continue;
else {
if (vis[u]==1) {continue;}
else {vis[u]=1; ++cnt[u];}
}
}
}
}
void solve() {
dfs(1, 0);
int ans=0;
for (int i=1; i<=n; ++i) ans+=cnt[i];
cout<<ans<<' '<<len<<endl;
exit(0);
}
}
namespace task1{
int v[N], cnt, len;
void solve() {
for (int i=1; i<n; ++i) v[i]=e[head[i]].val;
int lst=-1, clen=0;
bool con=0, other=0;
for (int i=1; i<=n; ++i) {
if (v[i]==1) {
if (v[i]!=lst) {
if (con) len+=clen+1, lst=v[i];
else ++cnt, ++len, lst=v[i];
}
else ++len;
other=0; con=0; clen=0;
}
else if (!v[i]) con=0, other=1, clen=0;
else {
if (lst==1 && !other) con=1, clen=1, other=0;
if (lst==2 && !other) ++clen;
if (lst==0) con=0, clen=0, other=1;
}
lst=v[i];
}
cout<<cnt<<' '<<len<<endl;
exit(0);
}
}
namespace task2{
struct sit{int cnt, len; inline void build(int c_, int l_) {cnt=c_; len=l_;}}dp[N][2];
void dfs(int u, int fa) {
int minn=INF, dlt=0;
int t1, t2;
// fa->0
int cnta1=0, cnta2=0, len1=0;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
dfs(v, u);
if (e[i].val==1) {
++cnta1; cnta2+=dp[v][1].cnt; len1+=dp[v][1].len+1;
}
else if (!e[i].val) {
cnta2+=dp[v][0].cnt; len1+=dp[v][0].len;
}
}
dp[u][0].build(cnta2+(cnta1%2), len1);
// fa->1
int cntb1=1, cntb2=0, len2=0;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
if (e[i].val==1) {
++cntb1; cntb2+=dp[v][1].cnt; len2+=dp[v][1].len+1;
}
else if (!e[i].val) {
cntb2+=dp[v][0].cnt; len2+=dp[v][0].len;
}
}
dp[u][1].build(cntb2+(cntb1%2), len2);
}
void solve() {
dfs(1, 0);
#if 1
cout<<"---dp---"<<endl;
for (int i=1; i<=n; ++i) cout<<dp[i][0].cnt<<' '<<dp[i][0].len<<' '<<dp[i][1].cnt<<' '<<dp[i][1].len<<endl;
cout<<"---dp---"<<endl;
#endif
printf("%d %d\n", dp[1][0].cnt/2, dp[1][0].len);
exit(0);
}
}
namespace task{
struct sit{int cnt, len; inline void build(int c_, int l_) {cnt=c_; len=l_;}}dp[N][2];
inline bool operator < (sit a, sit b) {return a.cnt==b.cnt?a.len<b.len:a.cnt<b.cnt;}
inline bool cmp(int cnta, int lena, int cntb, int lenb) {return cnta==cntb?lena<lenb:cnta<cntb;}
void dfs(int u, int fa) {
int cnta2=0, len1=0;
int cntb2=0, len2=0;
int cnt[2]={0, INF}, len[2]={0, INF};
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v==fa) continue;
dfs(v, u);
cnta2=cnt[0], len1=len[0];
cntb2=cnt[1], len2=len[1];
if (e[i].val==1) {
cnt[1]=cnta2+dp[v][1].cnt, len[1]=len1+dp[v][1].len+1;
cnt[0]=cntb2+dp[v][1].cnt, len[0]=len2+dp[v][1].len+1;
}
else if (!e[i].val) {
cnt[0]=cnta2+dp[v][0].cnt, len[0]=len1+dp[v][0].len;
cnt[1]=cntb2+dp[v][0].cnt, len[1]=len2+dp[v][0].len;
}
else {
if (cmp(cnta2+dp[v][0].cnt, len1+dp[v][0].len, cntb2+dp[v][1].cnt, len2+dp[v][1].len+1))
cnt[0]=cnta2+dp[v][0].cnt, len[0]=len1+dp[v][0].len;
else cnt[0]=cntb2+dp[v][1].cnt, len[0]=len2+dp[v][1].len+1;
if (cmp(cntb2+dp[v][0].cnt, len2+dp[v][0].len, cnta2+dp[v][1].cnt, len1+dp[v][1].len+1))
cnt[1]=cntb2+dp[v][0].cnt, len[1]=len2+dp[v][0].len;
else cnt[1]=cnta2+dp[v][1].cnt, len[1]=len1+dp[v][1].len+1;
}
}
//assert(cnt[0]==cnt[1]);
if (cmp(cnt[0], len[0], cnt[1]+1, len[1]))
dp[u][0].build(cnt[0], len[0]);
else dp[u][0].build(cnt[1]+1, len[1]);
if (cmp(cnt[0]+1, len[0], cnt[1], len[1]))
dp[u][1].build(cnt[0]+1, len[0]);
else dp[u][1].build(cnt[1], len[1]);
//dp[u][0].build(cnt[0], len[0]);
//dp[u][1].build(cnt[1]+1, len[1]);
}
void solve() {
dfs(1, 0);
#if 0
cout<<"---dp---"<<endl;
for (int i=1; i<=n; ++i) cout<<dp[i][0].cnt<<' '<<dp[i][0].len<<' '<<dp[i][1].cnt<<' '<<dp[i][1].len<<endl;
cout<<"---dp---"<<endl;
#endif
printf("%d %d\n", dp[1][0].cnt/2, dp[1][0].len);
exit(0);
}
}
signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
bool flag=1, chain=1;
n=read();
for (int i=1,a,b,c,d; i<n; ++i) {
a=read(); b=read(); c=read(); d=read();
if (d==2) add(a, b, 2), add(b, a, 2);
else {add(a, b, c^d), add(b, a, c^d); flag=0;}
if (b!=a+1) chain=0;
}
//if (flag) {puts("0 0"); return 0;}
//if (chain) task1::solve();
//force::solve();
//task2::solve();
task::solve();
return 0;
}
题解 w的更多相关文章
- [codevs1157]2^k进制数
[codevs1157]2k进制数 试题描述 设r是个2k 进制数,并满足以下条件: (1)r至少是个2位的2k 进制数. (2)作为2k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. ...
- $exLucas$学习笔记
本来不打算写了的,,,但是感$jio$理解起来还是有点儿难度的来着,,,$so$还是瞎写点儿趴$QAQ$ $exLucas$主要有三步: 1)唯一分解$mod$并预处理$p^{k}$以内的阶乘 2)计 ...
- lucene入门创建索引——(二)
1.程序宏观结构图
- [NOIP10.3模拟赛]3.w题解--神奇树形DP
题目链接: 咕 闲扯: 这题考场上把子任务都敲满了,5个namespace,400行11k 结果爆0了哈哈,因为写了个假快读只能读入一位数,所以手测数据都过了,交上去全TLE了 把边分成三类:0. 需 ...
- csp-s模拟测试53u,v,w题解
题面:https://www.cnblogs.com/Juve/articles/11602450.html u: 用差分优化修改 二维差分:给(x1,y1),(x2,y2)加上s: $d[x1][y ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
随机推荐
- python3.7验证码识别MuggleOCR,为什么总是报错
先来看看MuggleOCR简介(白嫖)这是一个为麻瓜设计的本地OCR模块只需要简单几步操作即可拥有两大通用识别模块,让你在工作中畅通无阻. 这套模型是基于 https://github.com/ker ...
- ARTS第十一周
受辞职考研和新冠肺炎疫情影响,一直没更.遗憾,数学和专业课再高点就有戏了.继续. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3. ...
- ARTS第七周
补上.瞎忙,看来还是效率的问题. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至少一个技术技巧4.Share:分享 ...
- 安卓源码默认开启USB调试
找到\frameworks\base\services\usb\java\com\android\server\usb\UsbDeviceManager.java下的 Settings.Global. ...
- 使用vue-preview报错Cannot read property 'open' of undefined
最近在做一个vue项目中时,需要使用vue-preview插件制作缩略图,首先在终端使用npm i vue-preview -S指令安装了vue-preview插件,然后在main.js中,导入并引用 ...
- 02_Java基础类型和包装类型
基本数据类型 包装类名称 所占字节数 默认值 byte Byte 1 0 short Short 2 0 Int Integer 4 0 long Long 8 0L double Double 8 ...
- 第七篇 -- 常用界面组件的使用(QSlider和QProgressBar)
首先画个图 ui_proBar.py # -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'ui_ ...
- 初学MyBatis(踩坑)Error querying database. Cause: java.sql.SQLException: java.lang.ClassCastException: java.math.BigInteger cannot be cast to java.lang.Long
最近在学习Mybatis,代码全部根据教程写好了,一运行结果报了一个错误,主要错误内容: Caused by: org.apache.ibatis.exceptions.PersistenceExce ...
- PS Lite - 源码解读
PostOffice 类 /** * \brief 系统的中心. */ class Postoffice { public: /** * \brief 返回单例对象. */ static Postof ...
- netty系列之:中国加油
目录 简介 场景规划 启动Server 启动客户端 消息处理 消息处理中的陷阱 总结 简介 之前的系列文章中我们学到了netty的基本结构和工作原理,各位小伙伴一定按捺不住心中的喜悦,想要开始手写代码 ...