AtCoder 3913 XOR Tree

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/82933180

套路,每个点的值等于所有与它相邻的边的值的亦或值

对一段路径亦或,相当于对这段路径末端的2个点亦或,所有路径变成0,也就是把所有点变成0;

所以统计所有点的值,相同就直接亦或他们之间的路径,然后消掉,不相同的,1-15最多1个,那么就状压DP一蛤

#include<bits/stdc++.h>
#define maxl 100010
#define inf 2000000001

using namespace std;

int n,ans,res;
int a[maxl],dp[maxl],cnt[16];

inline void prework()
{
	for(int i=0;i<n;i++)
		a[i]=0,cnt[i]=0;
	int u,v,val;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d%d",&u,&v,&val);
		a[u]^=val;a[v]^=val;
	}
	for(int i=0;i<n;i++)
		cnt[a[i]]++;
	res=0;ans=0;
	for(int i=1;i<16;i++)
	{
		ans+=cnt[i]/2;
		if(cnt[i]&1)
			res^=(1<<i);
	}		
}

inline int dfs(int s)
{
    if(s==0)
        return 0;
    if(dp[s])
        return dp[s];
    dp[s]=inf;
    for(int i=1;i<16;i++)
        if(s&(1<<i)){
            for(int j=1;j<16;j++){
                if(j!=i&&(s&(1<<j))){
                    int q=i^j;
                    if(s&(1<<q))
                        dp[s]=min(dp[s],dfs(s^(1<<i)^(1<<j)^(1<<q))+2);
                    else
                        dp[s]=min(dp[s],dfs(s^(1<<i)^(1<<j)^(1<<q))+1);
                }
            }

        }
    return dp[s];
}

inline void mainwork()
{
	int x=dfs(res);
	ans+=x;
}

inline void print()
{
	printf("%d\n",ans);
}

int main()
{
	while(~scanf("%d",&n))
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/82933180
今日推荐