Problem Statement

You are given a tree with N vertices. The vertices are numbered 0 through N−1, and the edges are numbered 1 through N−1. Edge i connects Vertex xi and yi, and has a value ai. You can perform the following operation any number of times:

  • Choose a simple path and a non-negative integer x, then for each edge e that belongs to the path, change ae by executing aeaex (⊕ denotes XOR).

Your objective is to have ae=0 for all edges e. Find the minimum number of operations required to achieve it.

Constraints

  • 2≤N≤105
  • 0≤xi,yiN−1
  • 0≤ai≤15
  • The given graph is a tree.
  • All input values are integers.

Input

Input is given from Standard Input in the following format:

N
x1 y1 a1
x2 y2 a2
:
xN−1 yN−1 aN−1

Output

Find the minimum number of operations required to achieve the objective.

Sample Input 1

5
0 1 1
0 2 3
0 3 6
3 4 4

Sample Output 1

3

The objective can be achieved in three operations, as follows:

  • First, choose the path connecting Vertex 1,2, and x=1.
  • Then, choose the path connecting Vertex 2,3, and x=2.
  • Lastly, choose the path connecting Vertex 0,4, and x=4.

Sample Input 2

2
1 0 0

Sample Output 2

0

    (我什么时候能做ATCODER 1000分题了2333)
首先路径异或x 等于 路径两个端点到 树根 的路径 分别异或x,因为lca以上的边被异或了两次,所以就相当于路径异或。
于是我们不妨把 从点i到根的路径异或x 叫做一次 基本操作,然后我们随便选一个点当根,最后所有边都为0 需要满足:
除了根节点以外,涉及一个点i的所有基本操作的x(一个点i会被在j产生的基本操作涉及当且仅当i是j的祖先)的异或和等于 i到父亲的边。 当然我们知道,两次x一样的基本操作是可以合并为 一个 题目中描述的操作的,那么我们先假设不知道这个,而是贪心的让基本操作次数最少。
那么如何让基本操作次数最少呢?
发现一个节点x的儿子son这颗子树对它的影响始终是 val(x,son) ,所以我们可以让每个节点只操作一次,取它所有邻接的边 异或起来的值(如果是0当然可以不操作)。
于是就得到了 基本操作最少的 方案, 并且这个方案是唯一的,因为从子树到根每一步都是唯一的。 但是如果可以合并的话,反例就很好找了: 1,4,5. 不能合并的话只能三步达成,但是合并的话,可以 1,4,5->0,5,5->0,0,0,两步就行了。
不过我们可以很容易的发现,如果很多点的操作x一样,可以先把这些一样的x合并起来,这样答案总是最优的。
这样之后,剩下的操作x互不相同,且1<=x<=15 (0没有意义),很容易想到用 状态压缩下的dp来解决。但是状态之间可能有后效性,所以这个时候就不能
直接在DAG上dp了,要跑spfa。 所以最后我们枚举哪个点是根(也就是哪个点的 邻接的边的异或和 可以不计入统计),更新一下答案的最小值即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100005;
int val[maxn*20],hd[maxn],n,m;
int to[maxn*20],ne[maxn*20],num,S;
int XS[maxn],now,ci[20],d[maxn],C[233];
inline void add(int x,int y,int z){ to[++num]=y,ne[num]=hd[x],hd[x]=num,val[num]=z;} inline void build(){
for(int i=1;i<ci[15];i++)
for(int j=1;j<=15;j++) if(ci[j-1]&i){
now=i^ci[j-1],add(now,i,1);
for(int k=1;k<=15;k++) if(ci[k-1]&now) add(now^ci[k-1]^ci[(j^k)-1],i,1+((now&ci[(j^k)-1])?1:0));
}
} inline void spfa(){
queue<int> q; bool v[maxn];
memset(d,0x3f,sizeof(d));
memset(v,0,sizeof(v));
d[0]=0,q.push(0),v[0]=1; int x;
while(!q.empty()){
x=q.front(),q.pop();
for(int i=hd[x];i;i=ne[i]) if(d[x]+val[i]<d[to[i]]){
d[to[i]]=d[x]+val[i];
if(!v[to[i]]) v[to[i]]=1,q.push(to[i]);
}
v[x]=0;
}
} inline void init(){
ci[0]=1;
for(int i=1;i<=15;i++) ci[i]=ci[i-1]<<1; build();
spfa();
} inline void solve(){
int uu,vv,ww,ans=1<<30;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d%d",&uu,&vv,&ww);
uu++,vv++,XS[uu]^=ww,XS[vv]^=ww;
} for(int i=1;i<=n;i++) C[XS[i]]++;
for(int i=1;i<=n;i++){
C[XS[i]]--; S=0,now=0;
for(int j=1;j<=15;j++){
now+=C[j]>>1;
S|=(C[j]&1)*ci[j-1];
}
now+=d[S];
ans=min(ans,now); C[XS[i]]++;
} printf("%d\n",ans);
} int main(){
init();
solve();
return 0;
}

  

												

AtCoder - 3913 XOR Tree的更多相关文章

  1. [多校联考2019(Round 5 T1)] [ATCoder3912]Xor Tree(状压dp)

    [多校联考2019(Round 5)] [ATCoder3912]Xor Tree(状压dp) 题面 给出一棵n个点的树,每条边有边权v,每次操作选中两个点,将这两个点之间的路径上的边权全部异或某个值 ...

  2. 「AGC035C」 Skolem XOR Tree

    「AGC035C」 Skolem XOR Tree 感觉有那么一点点上道了? 首先对于一个 \(n\),若 \(n\equiv 3 \pmod 4\),我们很快能够构造出一个合法解如 \(n,n-1, ...

  3. Solution -「AT 3913」XOR Tree

    \(\mathcal{Description}\)   Link.   给定一棵树,边 \((u,v)\) 有边权 \(w(u,v)\).每次操作可以使一条简单路径上的边权异或任意非负整数.求最少的操 ...

  4. 【思维题 状压dp】APC001F - XOR Tree

    可能算是道中规中矩的套路题吧…… Time limit : 2sec / Memory limit : 256MB Problem Statement You are given a tree wit ...

  5. Atcoder D - XOR Replace(思维)

    题目链接:http://agc016.contest.atcoder.jp/tasks/agc016_d 题解:稍微想一下就知道除了第一次的x是所有的异或值,之后的x都是原先被替换掉的a[i]所以要想 ...

  6. AT3913 XOR Tree

    经过长时间的思考,我发现直接考虑对一条链进行修改是很难做出本题的,可能需要换一个方向. 可以发现本题中有操作的存在,是没有可以反过来做的做法的,因此正难则反这条路应该走不通. 那么唯一的办法就是简化这 ...

  7. 题解-AtCoder Code-Festival2017 Final-J Tree MST

    Problem \(\mathrm{Code~Festival~2017~Final~J}\) 题意概要:一棵 \(n\) 个节点有点权边权的树.构建一张完全图,对于任意一对点 \((x,y)\),连 ...

  8. 【ATcoder】Xor Sum 2

    题目大意:给定一个 N 个点的序列,求有多少个区间满足\(\oplus_{i=l}^ra[i]=\sum\limits_{i=l}^ra[i]\). 题解: 小结论:\(a\oplus b=a+b\r ...

  9. AT3913 XOR Tree(巧妙转换+状压dp)

    Step1:首先定义一个点的权值为与其相连边的异或和.那么修改一条路径,权值改变的只有两个端点.边权都为0和点权都为0实质相同. Step2:那么现在和树的结构就没有什么关系了.每次选两个点,然后同时 ...

随机推荐

  1. Pytorch学习(一)—— 自动求导机制

    现在对 CNN 有了一定的了解,同时在 GitHub 上找了几个 examples 来学习,对网络的搭建有了笼统地认识,但是发现有好多基础 pytorch 的知识需要补习,所以慢慢从官网 API进行学 ...

  2. Head First Python (二)

    if...else... 1 movies = ["The Holy Grail",1975,"Terry Jones & Terry Gilliam" ...

  3. ASP.NET Web网站中App_Code文件夹的作用及使用场景

    原文地址:Web Site项目和ASP.NET Web Application中App_Code文件夹的作用作者:宾的宾 我现在要建一个ASP.NET的网站了,不难吧,开始动手.如下图: 这种方法建立 ...

  4. German Collegiate Programming Contest 2015 计蒜课

    // Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...

  5. AD转换器的参数介绍

    分辨率.参考电压这些地球人都知道的就不说了. 当“参考电压”和“分辨率”被确定后,每两个数值间的差值,即“步进量”. 上面的“步进量”在AD中称为1LSB(最低有效位,Least Significan ...

  6. Redhat7配置yum源(本地源和网络源)

    Redhat7配置yum源(本地源和网络源)   目录 一:配置本地yum源 二:配置网络yum源 YUM(Yellow dog Updater Modified): yum是基于RPM包构建的软件更 ...

  7. Nginx从入门到放弃-第3章 场景实战篇

    3-1场景实践篇内容介绍: 3-2 Nginx作为静态资源Web服务_静态资源类型: 3-3 Nginx作为静态资源web服务_CDN(内容分发网络)场景: 3-4 Nginx作为静态资源Web服务_ ...

  8. js 抓取页面数据

    数据抓取 主要思路和原理 在根节点document中监听所有需要抓取的事件 在元素事件传递中,捕获阶段获取事件信息,进行埋点 通过getBoundingClientRect() 方法可获取元素的大小和 ...

  9. 【Luogu】P3786萃香抱西瓜(状压DP)

    题目链接 水题,数据范围提示得太明显了吧,不用动脑子都能知道是状压. 不过还是有坑(当然更可能是我脑子有坑) f[i][j][k][l]表示当前是第i秒,萃香在(j,k),已经抱到的西瓜状态是l的最少 ...

  10. java面试题之Thread类中的start()和run()方法有什么区别

    start()方法被用来启动新创建的线程,而且start()内部调用了run()方法, 区别: 当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动: start()方法才会启动新 ...