#1192 : 简单的树嵌入
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
3 0 1 1 2
样例输出
-
2 0 0 1 0 1 1
描述
给定一棵n个点的无权树。定义两点i, j(0 ≤ i, j ≤ n - 1)间的距离d(i, j)为两点间树上最短路径的长度(边数)。
我们需要将这n个点映射到中的向量v0 = (v0, 0, ..., v0, m - 1), ..., vn - 1 = (vn - 1, 0, ..., vn - 1, m - 1)。定义两向量vi, vj间的L1距离为
我们希望对于所有0 ≤ i, j ≤ n - 1有d(i, j) = d1(vi, vj)。
输入
第一行n。下面n - 1行,其中第i行为两个空格分开的整数xi, yi,表示点xi和yi间有一条边。
n ≤ 100. 0 ≤ xi, yi ≤ n - 1.
输出
第一行m。下面n行,其中第i行为m个空格分开的整数vi - 1, 0, ..., vi - 1, m - 1。
要求m ≤ 100且 - 100 ≤ vi, j ≤ 100。并且,对于所有0 ≤ i, j ≤ n - 1,d(i, j) = d1(vi, vj)。
如果有多解,输出任意一组满足要求的解即可。
由于m可以自已定,且m最大是100,只需要把每个点,放在以根为基础,接下来与兄弟结点不同的位置处,其距离,自然就是相等的。
如根用0,子结点第一个为01第二个为001第三个为0001等等,先用宽搜得到个数,再用深搜确定解,就可以了。
#define N 205
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,a,b,vis[N],d[N];
vector<int> p[N],ans[N];
queue<int> q;
int num = 0;
void BFS(){
while(!q.empty())q.pop();
num = 0;
q.push(0);vis[0] = 0;
while(!q.empty()){
int top = q.front();q.pop();
vis[top] = num++;
FI(p[top].size()){
if(vis[p[top][i]]== -1){
vis[p[top][i]] = 0;
q.push(p[top][i]);
}
}
}
}
void DFS(int top,int fa){
while(ans[top].size() < vis[top]){
ans[top].push_back(0);
}
ans[top].push_back(1);
d[top] = 0;
FI(p[top].size()){
int g = p[top][i];
if(d[g] == -1){
FJ(ans[top].size())
ans[g].push_back(ans[top][j]);
DFS(g,top);
}
}
}
int main()
{
while(S(n)!=EOF)
{
fill(vis,-1);
FI(n)ans[i].clear(),p[i].clear();
FI(n-1){
S2(a,b);
p[a].push_back(b);
p[b].push_back(a);
}
BFS();
fill(d,-1);
DFS(0,-1);
printf("%d\n",num - 1);
FI(n){
bool isFirst = true;
for(int j = 1;j<ans[i].size();j++){
if(isFirst)
printf("%d",ans[i][j]),isFirst = false;
else
printf(" %d",ans[i][j]);
}
for(int j = ans[i].size();j<num;j++){
if(isFirst)
printf("0"),isFirst = false;
else
printf(" 0");
}
printf("\n");
}
}
return 0;
}