列表

详情


NC206079. 异或生成树

描述

在图论中,树是一种无向图,其中任意两个顶点间存在唯一一条路径。
给定一棵根为 1 含有 n 个点的树,每个点都有一个权值,通过删去一些点和边我们可以组成一棵新的树,我们规定一棵树的权值为这棵树所有的点权值的异或,问能够新生成的树权值最大为多少?

输入描述

输入包含多行,第一行包含一个数字  ,表示节点数目,
第二行包含 n 个数字 ,表示每个节点的权值,
接下来 n - 1 行每行包含两个整数 表示 u 与 v 之间有一条边连接。

输出描述

输出包含一行,代表新生成的树权值最大的最大值。

示例1

输入:

3
1 2 3
1 2
1 3

输出:

3

示例2

输入:

5
4 2 6 8 1
1 5
2 3 
1 3
3 4

输出:

14

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 7ms, 内存消耗: 628K, 提交时间: 2020-06-05 16:22:00

#include <bits/stdc++.h>

using namespace std;

int a[300],ans[300];
int dp[300][150];
vector<int>edge[300];

void dfs(int u,int pre){
	dp[u][a[u]]=1;
	for(int k=0;k<edge[u].size();k++){
		int v=edge[u][k];
		if(v==pre) continue;
		dfs(v,u);
		for(int i=0;i<=127;i++) ans[i]=dp[u][i];
		for(int i=0;i<=127;i++){
			for(int j=0;j<=127;j++){
				if(ans[i]&&dp[v][j]) dp[u][i^j]=1; 
			}
		}
	}
}

int main()
{
	int n;
	cin>>n;
    for(int i=1;i<=n;i++){
    	cin>>a[i];
	}
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	dfs(1,0);
	
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=127;j++){
			if(dp[i][j]) ans=max(ans,j);
		}
	}
	
	cout<<ans<<endl;
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 4ms, 内存消耗: 508K, 提交时间: 2020-07-01 14:44:20

#include<bits/stdc++.h>
using namespace std;

vector<int>R[105];
int i,j,k,n,ans=0;
bool DP[105][130]={0};
void DFS(int x,int fa)
{
	int i,j,k,l;
	for(i=0;i<R[x].size();i++)
	{
		j=R[x][i];
		if(j==fa)continue;
		DFS(j,x);
		bool V[130]={0};
		for(k=0;k<128;k++)V[k]=DP[x][k];
		for(k=0;k<128;k++)
		{
			if(!DP[j][k])continue;
			for(l=0;l<128;l++)
			if(V[l])DP[x][k^l]=1,ans=max(ans,k^l);
		}
	}
}
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&j),DP[i][j]=1,ans=max(ans,j);
    for(i=1;i<n;i++)
    {
    	scanf("%d%d",&j,&k);
    	R[j].push_back(k),R[k].push_back(j);
	}
	DFS(1,0);
	printf("%d\n",ans);
    return 0;
}

上一题