题目
给你N个节点的父节点Ai,当父节点和自己相同的时候就是根节点。
再你一个权值数组,要求节点到根的路的所有边加起来的权值dist,按权值数组的要求的大小关系存在。
当 P = 3,1,2,5,4 时 ,要求3节点最小,1节点第二小…以此类推。
要你提供一种合法的权值分配方案。即给每个节点到父节点的边赋值。
没有合法方案输出-1.
题解思路
树的题写的太少了,也挺怕这种题的。一开始就想什么dfs。
结果可以暴力的,我们按顺序给节点从小到大赋值即可。
儿子节点的值肯定比父节点大。所以他的顺序也必须在父节点后面。
我们直接考虑暴力,处理出每个节点到根节点的dist,其实也好处理,因为正确的顺序肯定是保证这个节点的父节点出现过的。
这样我们可以直接给这个节点的dist从小到大赋。
而这个节点的dist,就是赋的值减去父节点的dist。
这样赋值能保证dist只从0到n-1。
节点直接的关系一定要处理好。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f ;
const int N = 200100 ;
int a[N] ;
int dis[N] ;
long long valu[N] ;
long long c[N] ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while ( T-- )
{
int n ;
int root = -1 ;
cin >> n ;
for (int i = 1 ; i <= n ; i++ )
{
cin >> a[i] ;
if (a[i] == i )
{
root = i ;
}
}
for (int i = 1 ; i <= n ; i++ )
{
cin >> dis[i] ;
valu[i] = -1 ;
}
if ( dis[1] == root )
{
int falg = 1 ;
long long cnt = 1 ;
valu[root] = 0 ;
c[root] = 0 ;
for (int i = 2 ; i <= n ; i++ )
{
int sp = dis[i] ;
if (valu[a[sp]] == -1 )
{
falg = 0 ;
break ;
}
c[sp] = cnt++;
valu[sp] = c[sp] - c[a[sp]];
//cout << sum << "\n" ;
//cout << dis[i] << " " << a[dis[i]] << "\n" ;
//cout << valu[dis[i]] << " " << valu[a[dis[i]]] << "\n" ;
}
if (falg)
{
//dfs(root,-1) ;
for (int i = 1 ; i <= n ; i++ )
cout << valu[i] << " ";
cout << "\n" ;
}else
cout << "-1\n" ;
}else
cout << "-1\n" ;
}
return 0 ;
}