Solution:
这题乍一看毫无思路,但是仔细思考(指思考了两天),找到了突破口。
手玩一下样例,设最大值为 A i A_i Ai(在第 i i i个结点),那么在旅行若干次 i i i后,其相邻结点中会有一个 A j = A i A_j = A_i Aj=Ai(在第j个结点)。此时若 i i i < j j j,则继续旅行 i i i,使得 A j = A i + 1 A_j = A_i + 1 Aj=Ai+1。接下来应该旅行 j j j,而旅行一次 j j j后,因为 j j j的相邻结点中 i i i的 A A A值最大,且此时 A i A_i Ai又会大于(或等于,取决于 i i i和 j j j的大小关系)又应该旅行 i i i。
所以应该先旅游几天,若旅行完 M M M天 A i > A j A_i > A_j Ai>Aj(由 A A A数组中元素的范围可知,使 A i = A j A_i = A_j Ai=Aj的天数 < 2 31 2^{31} 231),则直接输出 i i i,否则接下来判断 M − ( A i − A j ) M - (A_i - A_j) M−(Ai−Aj)的奇偶性。
可以配合代码理解。
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 4000007;
const int INF = 99999999;
int T, N;
LL M;
int A[MAXN];
struct Edge {
int u, v, nxt;
Edge (int u = 0, int v = 0, int nxt = 0) : u(u), v(v), nxt(nxt) {}
}e[MAXN];
int fir[MAXN], tote;
struct Node {
int id, x;
bool operator < (const Node h) const {return x == h.x ? id > h.id : x < h.x;}
// 重载小于运算符,当x != h.x时比较x,当x == h.x时比较其id值。
Node (int id = 0, int x = 0) : id(id), x(x) {}
}mxi, mxj;
void Clear() {
memset(fir, 0, sizeof(fir));
tote = 0;
mxi = mxj = Node(INF, 0);
}
void addedge(int x, int y) {
e[++tote] = Edge(x, y, fir[x]);
fir[x] = tote;
}
int main() {
#ifdef test
freopen("test.txt", "r", stdin);
#endif
cin >> T;
while(T--) {
cin >> N >> M;
Clear();
for(int i = 1; i <= N; i++) {
scanf("%d", &A[i]);
Node h = Node(i, A[i]);
mxi = max(mxi, h);
}
if(N == 1) {
printf("1\n");
continue;
}
int x, y;
for(int i = 1; i < N; i++) {
scanf("%d %d", &x, &y);
addedge(x, y), addedge(y, x);
}
for(int i = fir[mxi.id]; i; i = e[i].nxt)
mxj = max(mxj, Node(e[i].v, A[e[i].v]));
//mxi代表A值最大的节点,mxj代表mxi相邻的节点中A值最大的那个点。
int h = mxi.x - mxj.x;
if(M < h) {cout << mxi.id << endl; continue;} // M不满足二者的差值。
M -= h;
mxj.x = mxi.x;
if(mxi < mxj) swap(mxi, mxj);
if(M & 1) cout << mxj.id << endl; // M&1 即 M%2==1
else cout << mxi.id << endl;
}
return 0;
}