zoukankan      html  css  js  c++  java
  • AtCoder

    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
    ",ans);
    }
    
    int main(){
    	init();
    	solve();
    	return 0;
    }
    

      



  • 相关阅读:
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 实现业务
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 开发流程
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 报表系统集成说明
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 处理报表
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 数据访问
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 分布式应用
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 实现插件
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 对象设计器使用帮助
    基于DotNet构件技术的企业级敏捷软件开发平台 AgileEAS.NET平台开发指南 数据层开发
    Jquery 中的CheckBox、 RadioButton、 DropDownList、CheckBoxList、RadioButtonList的取值赋值
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8861628.html
Copyright © 2011-2022 走看看