http://acm.hdu.edu.cn/showproblem.php?pid=6662는
CC의 B 모델로 - 거의 질문을 작성 TREE 아이디어. 이동하는 경로입니다.
경로를 이동해야하는 두 우리가 INF에서 진행해야하는 인상을 잎처럼 하위 트리에서 전송이 강제합니다. 노드가 케이스의 중간에 중단 될 수있는 경우 그렇지 않으면, 초기 값은 더 나쁜 하위 트리의 전송이가 공을 업데이트하지 않는 경우 경우, 0입니다.
각 점은 먼 지점 유사한 (최소 필수 같은 먼 참조)를 향하는되는 번호 요청을 참조.
F는 [U]는 노드 U 서브 트리 아래로 최적 값을 나타내고, 이것은 다시 잎 잎 DFS로 초기화되어야한다.
G는 [U]는 F [P]와 값을 최적 값으로 차선을 기록 할 수 있도록 U는 다음 (아버지의 P로부터 주위 다른 방향 조부 형 올 중 이동 중 아버지 노드로부터 상방으로 P를 나타낸다 이는 아들) 최적의 값이 자체를 초기화 할 때 DFS 루트를.
이 방법으로 특수 문장에 대답 통계 시간의 정의로 이어집니다.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
ll val[MAXN];
vector<int> E[MAXN];
int ROOT;
void dfs1(int u, int p) {
if(E[u].size() == 1) {
ROOT = u;
return;
}
for(auto v : E[u]) {
if(v == p)
continue;
dfs1(v, u);
if(ROOT != -1)
return;
}
}
const ll INF = 1e18 + 1e17;
const ll INF2 = 1e16;
struct F {
ll val;
int son;
} fm1[MAXN], fm2[MAXN], fM1[MAXN], fM2[MAXN], tmpm, tmpM;
inline void InitF(int n) {
for(int i = 1; i <= n; ++i) {
fm1[i].val = fm2[i].val = INF;
fM1[i].val = fM2[i].val = -INF;
fm1[i].son = fm2[i].son = fM1[i].son = fM2[i].son = -1;
}
}
void maintainF(int u, int v) {
if(tmpM.val < fm2[u].val) {
fm2[u] = tmpM;
fm2[u].son = v;
if(fm2[u].val < fm1[u].val) {
swap(fm1[u], fm2[u]);
}
}
if(tmpm.val > fM2[u].val) {
fM2[u] = tmpm;
fM2[u].son = v;
if(fM2[u].val > fM1[u].val) {
swap(fM1[u], fM2[u]);
}
}
}
void dfsF(int u, int p) {
if(E[u].size() == 1 && E[u][0] == p) {
fm1[u].val = val[u];
fM1[u].val = val[u];
fm1[u].son = u;
fM1[u].son = u;
return;
}
for(auto v : E[u]) {
if(v == p)
continue;
dfsF(v, u);
tmpM = fM1[v];
tmpm = fm1[v];
maintainF(u, v);
}
fm1[u].val += val[u];
fm2[u].val += val[u];
fM1[u].val += val[u];
fM2[u].val += val[u];
}
struct G {
ll val;
} gm[MAXN], gM[MAXN];
inline void InitG(int n) {
for(int i = 1; i <= n; ++i) {
gm[i].val = INF;
gM[i].val = -INF;
}
}
F getFm(int u, int p) {
if(fm1[p].son == u)
return fm2[p];
return fm1[p];
}
F getFM(int u, int p) {
if(fM1[p].son == u)
return fM2[p];
return fM1[p];
}
void maintainG(int u, int p) {
if(p == -1) {
gm[u].val = val[u];
gM[u].val = val[u];
return;
}
gm[u].val = max(getFM(u, p).val, gM[p].val) + val[u];
gM[u].val = min(getFm(u, p).val, gm[p].val) + val[u];
}
void dfsG(int u, int p) {
maintainG(u, p);
for(auto v : E[u]) {
if(v == p)
continue;
dfsG(v, u);
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld", &val[i]);
for(int i = 1, b; i <= n; ++i) {
scanf("%d", &b);
val[i] -= b;
}
for(int i = 1; i <= n; ++i)
E[i].clear();
for(int i = 1; i <= n - 1; ++i) {
int u, v;
scanf("%d%d", &u, &v);
E[u].push_back(v);
E[v].push_back(u);
}
ROOT = -1;
dfs1(1, -1);
//ROOT是其中一个叶子
InitF(n);
dfsF(ROOT, -1);
InitG(n);
dfsG(ROOT, -1);
ll ans = -INF;
for(int i = 1; i <= n; ++i) {
ll tmp = (E[i].size() == 1 && i != ROOT ? INF : fm1[i].val);
tmp = min(tmp, (i != ROOT) ? (gm[i].val) : INF);
ans = max(ans, tmp);
}
printf("%lld\n", ans);
}
return 0;
}
그것은 F와 G의 정의가 전송 된 서브 트리 / 아버지 엄격해야한다면, 그것은 특별한 문장을 필요로하지 않습니다 아닌가요?