题面
n个点的树,告诉2到n-1号点,到1,n的距离,还原这棵树 spj
考虑1-n之间没有其他点,则距离相减为非0定值,将其他点挂在1或n即可
1-n有其他点,则这些点的a[i]+b[i]最小,然后将其它点挂在下面就好
#include<bits/stdc++.h>
using namespace std;
const int maxn = 510000;
int n, a[maxn], b[maxn];
void init(){
scanf("%d", &n);
for (int i = 2; i < n; i ++)
scanf("%d", &a[i]);
for (int i = 2; i < n; i ++)
scanf("%d", &b[i]);
}
map<int, int> mp;
int main(){
init();
if (n == 2) return puts("TAK"), puts("1 2 1"), 0;
bool flag = 1;
for (int i = 2; i < n; i ++)
if (a[i] == b[i] || abs(a[i] - b[i]) != abs(a[2] - b[2])){
flag = 0;
break;
}
if (flag){
puts("TAK");
for (int i = 2; i < n; i ++)
if (a[i] > b[i])
printf("%d %d %d\n", n, i, b[i]);
else printf("%d %d %d\n", i, 1, a[i]);
printf("%d %d %d\n", 1, n, abs(a[2] - b[2]));
return 0;
}
int minn = INT_MAX;
for (int i = 2; i < n; i ++)
minn = min(minn, a[i] + b[i]);
mp[0] = 1, mp[minn] = n;
for (int i = 2; i < n; i ++){
if (a[i] + b[i] == minn)
if (!mp[a[i]]) mp[a[i]] = i;
else return puts("NIE"), 0;
}
for (int i = 2; i < n; i ++){
if (a[i] + b[i] != minn &&
((a[i] + b[i] - minn) % 2 || !mp[a[i] - (a[i] + b[i] - minn) / 2]))
return puts("NIE"), 0;
}
puts("TAK");
for (map<int,int>::iterator p = mp.begin();;){
if (p->first == minn) break;
map<int,int>::iterator q = p;
q ++;
printf("%d %d %d\n", p->second, q->second, q->first - p->first);
p = q;
}
for (int i = 2; i < n; i ++){
if (a[i] + b[i] != minn){
int dis = a[i] - (a[i] + b[i] - minn) / 2;
printf("%d %d %d\n", mp[dis], i, a[i] - dis);
}
}
return 0;
}