愿题目翻译:
您将得到一个由𝑛顶点组成的有根树。顶点编号从1到𝑛。任何顶点都可以是树的根。
树是没有循环的连通无向图。有根树是一棵有选定顶点的树,称为根。
树由包含𝑛数字的祖先数组𝑏指定:𝑏𝑖是数字为𝑖的顶点的祖先。顶点𝑢的祖先是一个顶点,它是从𝑢到根的简单路径上的下一个顶点。例如,在从5到3(根)的简单路径上,下一个顶点是1,因此5的祖先是1。
根没有祖先,因此对于它,𝑏𝑖的值是𝑖(根是𝑏𝑖=𝑖的唯一顶点)。
例如,如果𝑛=5和𝑏=[3,1,3,3,1],那么树看起来像这样。
一个𝑛=5的根树示例,树的根是顶点数3。
给定一个数组𝑝—树的顶点排列。如果可能的话,在边缘上赋任何正整数的权重,这样顶点按到根的距离排序就会形成给定的排列𝑝。
换句话说,对于给定的顶点排列𝑝,有必要选择这样的边权值,使条件𝑑𝑖𝑠𝑡[𝑝𝑖]<𝑑𝑖𝑠𝑡[𝑝𝑖+1]对于从1到𝑛−1的每个𝑖都成立。𝑑𝑖𝑠𝑡[𝑢]是从根到𝑢的路径上的边的权值之和。特别是,如果顶点𝑢是树的根,则𝑑𝑖𝑠𝑡[𝑢]=0。
例如,假设𝑝=[3,1,2,5,4]。在这种情况下,下面的边权满足这个排列:
边(3,4)的权值为102;
边(3,1)的权值为1;
边(1,2)的权值为10;
边(1,5)的权值是100。
到根的距离数组看起来像:𝑑𝑖𝑠𝑡=[1,11,0102,101]。通过增加到根的距离来排序的顶点形成给定的排列𝑝。
打印所需的边权值,或者确定没有合适的方法分配权值。如果有几个解决方案,那么打印其中任何一个。
输入
第一行输入数据包含一个整数𝑡(1≤𝑡≤104)—测试中输入数据集的数量。
每个测试用例由三行组成。
其一为整数𝑛(1≤𝑛≤2⋅105)。它是树中顶点的数量。
第二行包含𝑛整数𝑏1𝑏2,…,𝑏𝑛(1≤𝑏𝑖≤𝑛)。可以保证𝑏数组编码了一些根树。
第三行包含不同整数𝑝1,𝑝2,…,𝑝𝑛(1≤𝑝𝑖≤𝑛)的给定排列𝑝:𝑛。
保证测试中所有测试用例𝑛的值之和不超过2⋅105。
输出
对于每一组输入数据,将答案打印在单独的一行上。
如果解决方案存在,则打印𝑛整数数组𝑤1,𝑤2,…,𝑤𝑛,其中𝑤𝑖是从𝑏𝑖到𝑖的边的权值。对于根结点没有这样的边,因此使用值𝑤𝑖=0。对于所有其他顶点,𝑤𝑖的值必须满足不等式1≤𝑤𝑖≤109。𝑤𝑖值之间可以有相等的数,但是从根到顶点的所有边的权重之和必须不同,并且满足给定的排列。
如果有几个解,输出其中任何一个。
如果不存在,则输出-1。
例子
inputCopy
4
5
3 1 3 3 3 1
3 1 2 5 4
3.
1 1 2
3 1 2
7
1 1 2 3 4 5 6
1 2 3 4 5 6 7
6
4 4 4 4 4 1 1
4 2 1 5 6 3
outputCopy
1 100 102 100
-1
0 3 100 1 1 2 4
6 5 10 0 2 3
请注意
在该语句的主要部分分析了该示例的第一组输入数据。
在该示例的第二组输入数据中,不可能分配正权重来获得给定的顶点排列。
———————————————————————————————————————————
大致题意:给你一棵树,按照所给的根节点排列要求分配边权的值。如果可以满足该排列,则输出,每个边权所赋的值,不存在则输出-1。
———————————————————————————————————————————
刚开始以为要建图遍历等等,后来发现,满足该排列的条件。
到达根节点的dist值一定比父亲节的dist的值要大。
换而言之,如果要符合,那么在出现之前,那么它的父节点之前已经出现过了。
所以我们可以直接给边暴力赋值,每次都让它根据上一条边递增,如果上一条边不存在,则表示在的后面,不符合,直接return -1即可
——————————————————————————————————————————— 下面是代码的实现:
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long ll;
int n,t,m;
int as[200005];
int a[200005];
void solv(){
cin>>n;
vector<int>q[n+1];
int root;
for (int i =1; i<=n; i++) {
cin>>as[i];
if (as[i]==i) {
root=i;
}
}
for (int i =1; i<=n; i++) {
cin>>a[i];
}
if (a[1]!=root) {
printf("-1\n");
return;
}
int dis[200005];
for (int i =0; i<=n; i++) {
dis[i]=-1;
}
dis[root]=0;
for (int i =2; i<=n; i++) {
if (dis[as[a[i]]]==-1) {
printf("-1\n");return;
}
dis[a[i]]=dis[a[i-1]]+1;
}
for (int i =1; i<=n; i++) {
printf("%d ",dis[i]-dis[as[i]]);
}
printf("\n");
}
int main(){
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cin>>t;
while (t--) {
solv();
}
return 0;
}