题意:有一棵n个节点树,请你构造节点数据使图正好为这棵树(节点之间有边仅这二个节点位与等于 -1)。
思路:我们可以先黑白染色,因为n<=100,所以一定会有一种颜色少于等于50,所以我们就应该从位上考虑,不然为什么n<=100而不是小于100000呢,又因为只有相邻黑白节点才连接,所以我们可以考虑:将少的染成白色, -1用二进制表示为第0-59位都为1.
白色:最高位为0,白色编号的位为0,其余位为1.
黑色:最高位为1,相邻白色的编号的位为1,其余位为0.
这样染色,因为白色最高位为0,所以白色与白色一定不连接。
因为白色个数小于等于50,所以黑色有些位都为0,所以黑色与黑色一定不连接。
相邻的黑白色由于白色为0的位相邻黑色在该位为1,所以相邻黑白色是连接的。
不相邻的黑白色由于白色为0的位不相邻黑色在该位为0(如果为1则说明相邻),所以不相邻黑白色是不连接的。
所以此构造方法正确。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=1e9+7;
vector<int> g[1005];
int h=0, b=0, vis[1005], se[1005];
ll jie[1005];
void hbdfs(int v,int f)
{
if(f==-1)
{
vis[v]=0;
}
else
{
vis[v]=1-vis[f];
}
if(vis[v]==1)
{
b++;
}
else
{
h++;
}
for(int i=0; i<g[v].size(); i++)
{
int u=g[v][i];
if(vis[u]==-1)
{
hbdfs(u,v);
}
}
}
int main()
{
int n;
scanf("%d",&n);
memset(vis,-1,sizeof(vis));
for(int i=1; i<n; i++)
{
int u, v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
hbdfs(1,-1);
int t=0, flag=0;
if(h<=b)
{
flag=0;
}
else
{
flag=1;
}
for(int i=1; i<=n; i++)
{
if(vis[i]==flag)
{
jie[i]=((1LL<<59)-1)-(1LL<<t);
se[i]=t;
t++;
}
}
for(int i=1; i<=n; i++)
{
if(vis[i]==1-flag)
{
jie[i]=(1LL<<59);
for(int j=0;j<g[i].size();j++)
{
jie[i]=jie[i]+(1LL<<se[g[i][j]]);
}
}
}
for(int i=1; i<=n; i++)
{
printf("%lld%c",jie[i],i==n?'\n':' ');
}
return 0;
}

京公网安备 11010502036488号