51nod"省選"模測 A 樹的雙直徑(樹形dp)
阿新 • • 發佈:2019-03-17
ret void || names mx2 ble 最大的 51nod include
題意
題目鏈接
Sol
比賽結束後才調出來。。不多說啥了,就是因為自己菜。
裸的up-down dp,維護一下一個點上下的直徑就行,一開始還想了個假的思路寫了半天。。
轉移都在代碼註釋裏
毒瘤題目卡空間
#include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second #define LL long long using namespace std; const int MAXN = 6e5 + 10; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A> inline void debug(A a){cout << a << '\n';} template <typename A> inline LL sqr(A x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } void print(__int128 x) { if (x>9) print(x/10); putchar('0'+x%10); } int N, p[MAXN * 2], ve[MAXN * 2]; long long f[MAXN], g[MAXN], mxpre[MAXN], mxsuf[MAXN], dl[MAXN], ul[MAXN]; __int128 ans; vector<Pair> v[MAXN]; void downdfs(int x, int fa) { f[x] = dl[x] = 0; for(auto &tp : v[x]) { int to = tp.fi, w = tp.se; if(to == fa) continue; downdfs(to, x); chmax(dl[x], f[x] + f[to] + w); chmax(f[x], f[to] + w); chmax(dl[x], dl[to]); } } void updfs(int x, int fa) { int cnt = 0; for(int i = 0; i < v[x].size(); i++) if(v[x][i].fi != fa) p[++cnt] = v[x][i].fi, ve[cnt] = v[x][i].se; mxpre[0] = 0; mxsuf[cnt + 1] = 0; for(int i = 1; i <= cnt; i++) mxpre[i] = max(mxpre[i - 1], f[p[i]] + ve[i]); for(int i = cnt; i >= 1; i--) mxsuf[i] = max(mxsuf[i + 1], f[p[i]] + ve[i]); //一個點向上的直徑: //1: 從父親的ul繼承過來 //2: 前後綴中的最大值f + 出邊 + 入邊 //3: 父親的g + 兄弟節點中最大的f + 出邊 //4: 前驅/後繼 中的最大和次大 //5: 前驅/後繼 中的子樹中的直徑 for(int i = 1; i <= cnt; i++) { int to = p[i], w = ve[i]; chmax(g[to], g[x] + w); chmax(g[to], max(mxpre[i - 1], mxsuf[i + 1]) + w); chmax(ul[to], ul[x]);//1 chmax(ul[to], mxpre[i - 1] + mxsuf[i + 1]);//2 chmax(ul[to], g[x] + max(mxpre[i - 1], mxsuf[i + 1]));//3 } long long mx1 = -1e18, mx2 = -1e18, mx3 = -1e18; for(int i = 1; i <= cnt; i++) { chmax(ul[p[i]], max(mx1 + mx2, mx3)); int tmp = f[p[i]] + ve[i]; if(tmp > mx1) chmax(mx2, mx1), mx1 = tmp; else if(tmp > mx2) mx2 = tmp; chmax(mx3, dl[p[i]]); } mx1 = -1e18, mx2 = -1e18, mx3 = -1e18; for(int i = cnt; i >= 1; i--) { chmax(ul[p[i]], max(mx1 + mx2, mx3)); int tmp = f[p[i]] + ve[i]; if(tmp > mx1) chmax(mx2, mx1), mx1 = tmp; else if(tmp > mx2) mx2 = tmp; chmax(mx3, dl[p[i]]); } for(int i = 0; i < v[x].size(); i++) if(v[x][i].fi != fa) updfs(v[x][i].fi, x); } signed main() { //freopen("a.in", "r", stdin); N = read(); for(int i = 1; i <= N - 1; i++) { int x = read(), y = read(), w = read(); v[x].push_back(MP(y, w)); v[y].push_back(MP(x, w)); } downdfs(1, 0); updfs(1, 0); for(int i = 2; i <= N; i++) chmax(ans, (__int128) dl[i] * ul[i]); for(int i = 1; i <= N; i++) for(auto &tp : v[i]) tp.se = -tp.se; memset(ul, 0, sizeof(ul)); memset(g, 0, sizeof(g)); downdfs(1, 0); updfs(1, 0); for(int i = 2; i <= N; i++) chmax(ans, (__int128) dl[i] * ul[i]); print(ans); //cout << ans; return 0; }
51nod"省選"模測 A 樹的雙直徑(樹形dp)