题目背景
小v带萌萌的妹妹去玩,妹妹想去女仆咖啡馆,小v想去桌游吧。
妹妹:“我问你个问题,答不对你就做我一天的奴隶,答对了就今天我就全部听你的。”
小v:“全部都听!?”
妹妹:“嘻嘻嘻,你还是回答问题吧!”
于是小v为了自己一天的幸福,来向你求助。
题目描述
小v所在的世界被规划成了树形结构,每一个节点上都可以建一个女仆咖啡厅或者桌游吧或者什么都不建。在确定点1为根节点之后,规划局要求:对于每一个非叶子的节点i,设它子树(包括自己)中所有的女仆咖啡厅的数量为cafe[i],桌游吧数目为table[i],都有cafe[i]等于table[i]。
妹妹的问题是:这颗树最多能放多少个女仆咖啡厅。
输入输出格式
输入格式:
第一行,一个正整数N
第二至N行,每行两个正整数ui,vi,表示vi,ui有一条边。
输出格式:
只有一行,最多能放的女仆咖啡厅的个数。
输入输出样例
输入样例#1: 复制
5
1 2
2 3
3 4
2 5
输出样例#1: 复制
2
说明
对于30%的数据,1<=N<=20
对于100%的数据,1<=N<=10^5
洛谷题解:
正在我准备交题解时,发现有人提前交了,令我很尴尬于是我决定用一种OP的方法来诠释这道题
首先,AC链接
215ms比第二快15ms(然并卵)
好,开始正文
等等,我先解释一波,由于算法比较玄学,所以需要画图,然而蒟蒻我并不知道怎么把图传到网站上,所以,大家将就着拿笔画一下吧。。。
我们先看样例吧(其实是我懒的造数据),算了还是自己造吧,好像不太好,来一波输入(只有边)
1 2 2 3 3 4 4 5 5 6 4 7 2 8 好的就这样吧
先说点别的(感觉今天非常语无伦次)
首先如果答案想要增加,必然要有其它的叶节点的参与,因为内部节点全部为偶数,在内部节点间传递不会增加,所以内部节点间互不干扰,所以只要统计每个内部节点连接的叶节点数就好,因为内部节点算作自己的子树的一部分,所以如果一个内部节点连接的叶节点数为奇数,则内部节点开一个店,否则不开,那么很容易想到统计度数为一的点然后找唯一与其相连的点并使该点的权值加一,每当权值为奇数时就++ans,进一步,因为奇偶只看最后一位二进制,所以每次只要让权值异或1就好了,接下来,因为奇数时加而奇数时权值为一,那么我们简单粗暴一点,直接ans+=权值^=1就好
接下来上代码
1 #include <iostream>
2 using std::cin;
3 using std::cout;
4 using std::endl;
5 int n;
6 int u,v;
7 int ans;
8 int sum[100001];
9 bool ok[100001];
10 int b[100001];
11 inline void cl(int,int);
12 int main(){
13 std::ios::sync_with_stdio(false);
14 cin>>n;
15 for (int i=1;i<n;++i){
16 cin>>u>>v;
17 cl(u,v);
18 cl(v,u);
19 }
20 for (int i=1;i<=n;++i)
21 if (ok[i])
22 ans+=sum[b[i]]^=1;
23 cout<<ans<<endl;
24 }
25 inline void cl(int bg,int ed){
26 if (b[bg]==0){
27 b[bg]=ed;
28 ok[bg]=true;
29 }
30 else ok[bg]=false;
31 }