题意:有一棵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; }