题意
给定一棵树 假设两个点or值为 2^60-1 则这两个点会连一条边 问实现这棵树的话每个点的值为多少
思路
二分图 + 构造 先把所有点分成两份 每个集合内部不会连边 然后给这两个集合赋值 使得两个集合中连边的两点or值为2^60-1
记录一下哪个集合的点最少 然后给这个集合的每个点赋个序号 假设分为黑点白点 黑点最少 我们可以使黑点每位全赋值为1(除了最高位) 然后把它的序号位改为0(防止连到其他点) 而对于白点 我们可以全赋值为0最高位为1然后将它所连的两个点的序号位改为1
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 110;
int n;
int dep[N], fa[N], cnt[N];
ll ans[N];
bool flag = true;
int id;
vector<int> G[N];
void dfs(int u, int father, int depth)
{
dep[u] = depth;
if (dep[u] & 1) cnt[1] ++ ;
else cnt[0] ++ ;
for (int i = 0; i < G[u].size(); i ++ )
{
int to = G[u][i];
if (to == father) continue;
dfs(to, u, depth + 1);
}
}
int main()
{
cin >> n; id = 1;
for (int i = 1; i < n; i ++ )
{
ll u, v;
scanf("%lld%lld", &u, &v);
G[u].push_back(v); G[v].push_back(u);
}
dfs(1, 0, 1);
if (cnt[1] >= cnt[0]) flag = true;
else flag = false;
for (int i = 1; i <= n; i ++ )
{
if (dep[i] % 2)
{
if (flag) dep[i] = 0;
else dep[i] = id ++ ;
}
else
{
if (flag) dep[i] = id ++ ;
else dep[i] = 0;
}
}
for (int i = 1; i <= n; i ++ )
{
if (dep[i] == 0)
{
ans[i] = (1ll << 59);
for (int j = 0; j < G[i].size(); j ++ )
ans[i] += (1ll << dep[G[i][j]]);
}
else
{
ans[i] = (1ll << 60) - 1;
ans[i] -= (1ll << 59);
ans[i] -= (1ll << dep[i]);
}
cout << ans[i] << " ";
}
return 0;
}