• 世界树的考验「NOIP多校联考 2019」


    题意

    有一颗带边权的树,每次操作可以将一条路径上所有边权同时异或一个任意值,求最少多少次操作可以将所有边权变为0。

    (题目保证边权≤15)


    思路

    可以发现题目保证了边权,看到这个数字容易联想到状压(天知道为什么我没联想到)。

    由于边权不是很好处理,所以我们可以将其转换到点上面去,那么每一个点的点权就是与之相连的边权异或值。

    由于异或运算拥有自反性,所以原先路径的操作就相当于选取两个点,同时异或一个值。(路径中间的每一个点都被异或两次,相当于没有被异或)

    很显然相同权值的点可以两两一对先消掉,然后再考虑剩下的节点。

    那么我们设子状态(dp[s])表示将状态s消除所需的最小操作次数。(由于相同权值被两两消除,所以每一位最多为1)

    转移过程是显然的。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	
    	const int N=100100;
    	const int INF=2147483647;
    	
    	int n,ans,S;
    	int v[N],cnt[16];
    	int dp[(1<<16)];
    	
    	int dfs (int s) {
    		if (!s) return 0;
    		if (dp[s]<INF) return dp[s];
    		for (register int i=0; i<16; ++i) {
    			if (!((s>>i)&1)) continue;
    			for (register int j=0; j<16; ++j) {
    				if (!((s>>j)&1)) continue;
    				if (i==j) continue;
    				int p=i^j,x=(s-(1<<i)-(1<<j))^(1<<p);
    				if ((s>>p)&1) dp[s]=min(dp[s],dfs(x)+2);
    				else dp[s]=min(dp[s],dfs(x)+1);
    			}
    		}
    		return dp[s];
    	}
    
    	inline void MAIN () {
    		read(n);
    		for (register int i=1,a,b,c; i<n; ++i) {
    			read(a),read(b),read(c);
    			v[a]^=c,v[b]^=c;
    		}
    		for (register int i=0; i<n; ++i) ++cnt[v[i]];
    		for (register int i=1; i<16; ++i) ans+=(cnt[i]>>1),S|=(1<<i)*(cnt[i]&1);
    		for (register int i=0; i<(1<<16); ++i) dp[i]=INF;
    		write(ans+dfs(S));
    	}
    	
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
    
  • 相关阅读:
    Luogu6300 悔改 [FFT,阈值法]
    CF1016G Appropriate Team [Pollard-rho,FMT]
    AGC021F Trinity【计数,NTT】
    CF578F Mirror Box 【图论,Matrix-Tree】
    [ARC083]Collecting Balls
    HNCPC2019部分题解
    [LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)
    [CF960G]Bandit Blues(第一类斯特林数+分治卷积)
    [CF804F]Fake bullions
    [CF643E]Bear and Destroying Subtrees(期望,忽略误差)
  • 原文地址:https://www.cnblogs.com/ilverene/p/11619825.html
Copyright © 2020-2023  润新知