zoukankan      html  css  js  c++  java
  • FZOJ 4108 世界树的考验

    这题的转换非常的巧妙。

    众所周知,树上一条路径点权异或有非常好的性质,可惜这道题是边权啊,这就需要一个转化:

    • 设每个点的点权为与它相连的所有边的边权的异或和。那么使得每个点的点权为(0)就是题目要求达到的状态。
      证明:考虑度数为(1)的点,显然与他们相连的边为(0),然后把他们删掉,又会有很多度数为(1)的点(类似于拓扑排序)……最后可以推出所有边都变成(0)

    那么,每次操作把一条路径的每一条边异或同一个数(x),相当于把路径两端的点权都异或(x),其他点权都不变(大家可以自己考虑考虑)。

    现在问题变成了,给你若干个数(数值 (leq) 15),每次给两个数异或上同一个数,问至少多少次可以把所有数变成(0)

    显然相同的数直接异或掉就可以了,所以可以看成若干个不同的数。设(f[S])表示当状态为(S)时需要的最少操作数((i)属于集合(S)当且仅当 ((1<<i&S)!=0) ),其实就是一个状态压缩,然后发现状态总数非常少(只有(2^{16})种),所以可以直接一发记忆化搜索解决。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int N=100009,INF=1<<30;
    int siz[N],point[N],n,S,f[N*10];
    
    void init()
    {
    	scanf("%d",&n);
    	int x,y,z;
    	for (int i=1;i<n;i++)
    	{
    		scanf("%d %d %d",&x,&y,&z);
    		point[x]^=z,point[y]^=z;
    	}
    	for (int i=0;i<=n;i++)
    		siz[point[i]]++;
    }
    
    int dfs(int S)
    {
    	if(S==0)
    		f[S]=0;
    	if(f[S]!=INF)
    		return f[S];
    	for (int i=0;i<=15;i++)
    		if(S&1<<i)
    			for (int j=0;j<=15;j++)
    				if(i!=j&&(S&1<<j))
    				{
    					int p=S^(1<<i)^(1<<j)^(1<<(i^j));
    					if(S&(1<<(i^j)))
    						f[S]=min(f[S],dfs(p)+2);
    					else
    						f[S]=min(f[S],dfs(p)+1);
    				}
    	return f[S];
    }
    
    void work()
    {
    	int ans=0;
    	for (int i=1;i<=15;i++)
    		ans+=siz[i]/2,siz[i]&1?(S^=(1<<i)):0;
    	for (int i=0;i<1<<16;i++)
    		f[i]=INF;
    	printf("%d
    ",ans+dfs(S));
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    HDU 3572 Task Schedule(拆点+最大流dinic)
    POJ 1236 Network of Schools(Tarjan缩点)
    HDU 3605 Escape(状压+最大流)
    HDU 1166 敌兵布阵(分块)
    Leetcode 223 Rectangle Area
    Leetcode 219 Contains Duplicate II STL
    Leetcode 36 Valid Sudoku
    Leetcode 88 Merge Sorted Array STL
    Leetcode 160 Intersection of Two Linked Lists 单向链表
    Leetcode 111 Minimum Depth of Binary Tree 二叉树
  • 原文地址:https://www.cnblogs.com/With-penguin/p/12705843.html
Copyright © 2011-2022 走看看