给定一棵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)。
如果有多解,输出任意一组满足要求的解即可。
3 0 1 1 2
2 0 0 1 0 1 1
由于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; }