http://www.lydsy.com/JudgeOnline/problem.php?id=3732
/* Kruskal 最小生成树 树链剖分 最大值查询 注意:可能会有几块不联通的图 */ #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <ctime> using namespace std; const int N = 25010; #define gc getchar() #define lson jd << 1 #define rson jd << 1 | 1 int n, m, k, now = 1, tim, ans; int bef[N], data[N], fat[N], head[N], tree[N], topp[N], fa[N], son[N], siz[N], deep[N]; struct Node_1{int u, v, w;} E[N << 1]; struct Node_2{int u, v, w, nxt;} G[N << 2]; struct Node_3{int l, r, Max;} T[N << 2]; bool cmp(Node_1 a, Node_1 b) {return a.w < b.w;} struct Bzoj_3732{ inline int read(){ int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x; } inline int getf(int x) {return fat[x] == x ? x : fat[x] = getf(fat[x]);} inline void add(int u, int v, int w) {G[now].v = v; G[now].w = w; G[now].nxt = head[u]; head[u] = now ++;} inline void Kruskal(){ int js(0); for(int i = 1; i <= m; i ++){ int u = E[i].u, v = E[i].v; int fu = getf(u), fv = getf(v); if(fu != fv) { js ++; fat[fu] = fv; add(u, v, E[i].w); add(v, u, E[i].w); } if(js == n - 1) return ; } } void dfs_find_son(int u, int f_, int dep){ fa[u] = f_; deep[u] = dep; siz[u] = 1; for(int i = head[u]; ~ i; i = G[i].nxt){ int v = G[i].v; if(v != f_){ data[v] = G[i].w; dfs_find_son(v, u, dep + 1); siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; } } } void dfs_to_un(int u, int tp){ topp[u] = tp; tree[u] = ++ tim; bef[tim] = u; if(!son[u]) return ; dfs_to_un(son[u], tp); for(int i = head[u]; ~ i; i = G[i].nxt){ int v = G[i].v; if(v != fa[u] && v != son[u]) dfs_to_un(v, v); } } void build_tree(int l, int r, int jd){ T[jd].l = l; T[jd].r = r; if(l == r) {T[jd].Max = data[bef[l]]; return ;} int mid = (l + r) >> 1; build_tree(l, mid, lson); build_tree(mid + 1, r, rson); T[jd].Max = max(T[lson].Max, T[rson].Max); } void Sec_A(int l, int r, int jd, int x, int y){ if(x <= l && r <= y) {ans = max(ans, T[jd].Max); return ;} int mid = (l + r) >> 1; if(x <= mid) Sec_A(l, mid, lson, x, y); if(y > mid) Sec_A(mid + 1, r, rson, x, y); } inline int Sec_A_imp(int x, int y){ int tp1 = topp[x], tp2 = topp[y], ret = 0; while(tp1 != tp2){ if(deep[tp1] < deep[tp2]) swap(x, y), swap(tp1, tp2); ans = 0; Sec_A(1, n, 1, tree[tp1], tree[x]); ret = max(ans, ret); x = fa[tp1]; tp1 = topp[x]; } if(x == y) return ret; if(deep[x] < deep[y]) swap(x, y); ans = 0; Sec_A(1, n, 1, tree[y] + 1, tree[x]); ret = max(ret, ans); return ret; } }AC; int main() { n = AC.read(), m = AC.read(); k = AC.read(); for(int i = 1; i <= n; i ++) fat[i] = i, head[i] = -1; for(int i = 1; i <= m; i ++) E[i].u = AC.read(), E[i].v = AC.read(), E[i].w = AC.read(); sort(E + 1, E + m + 1, cmp); AC.Kruskal(); for(int i = 1; i <= n; i ++) if(!deep[i]) AC.dfs_find_son(i, 0, 1); for(int i = 1; i <= n; i ++) if(!topp[i]) AC.dfs_to_un(i, i); AC.build_tree(1, n, 1); while(k --){ int x = AC.read(), y = AC.read(); int Answer = AC.Sec_A_imp(x, y); printf("%d\n", Answer); } return 0; }
与noip2013货车运输相似(一模一样)
货车运输:最大生成树 + 最小值查询
此题 :最小生成树 + 最大值查询
货车运输改几行代码就A了
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <string> using namespace std; const int N = 15010; #define oo 99999999 struct Node{ int u, v, w; }S[N << 1]; struct Edge{ int u, v, w, nxt; }E[N << 2]; int now = 1, n, m, js; int head[N], p[N], f[N][30], g[N][30], deep[N]; inline int read(){ int x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x; } inline bool cmp(Node a, Node b){ return a.w < b.w; } int getf(int x){ return p[x] == x ? x : p[x] = getf(p[x]); } void add(int u, int v, int w){ E[now].v = v; E[now].w = w; E[now].nxt = head[u]; head[u] = now ++; } inline void Kruskal(){ for(int i = 1, doen = 1; i <= (m << 1) && doen < n; i ++){ int u = S[i].u, v = S[i].v; int pu = getf(u), pv = getf(v); if(pu != pv){ p[pu] = pv; add(u, v, S[i].w); add(v, u, S[i].w); doen ++; } } } void make_deep(int u, int depth){ deep[u] = depth; for(int i = head[u]; ~ i; i = E[i].nxt){ int v = E[i].v; if(!deep[v]){ f[v][0] = u; g[v][0] = E[i].w; make_deep(v, depth + 1); } } } inline void make_jump(){ for(int j = 1; (1 << j) <= n; j ++) for(int i = 1; i <= n; i ++) if(f[i][j - 1]) f[i][j] = f[f[i][j - 1]][j - 1], g[i][j] = max(g[i][j - 1], g[f[i][j - 1]][j - 1]); } inline int lca(int x, int y){ int ret = -1; if(x == y) return 0; if(deep[x] < deep[y]) swap(x, y); int k = log2(deep[x]); for(int i = k; i >= 0; i --){ if(deep[f[x][i]] >= deep[y]){ ret = max(ret, g[x][i]); x = f[x][i]; } } if(x == y) return ret; for(int i = k; i >= 0; i --){ if(f[x][i] != f[y][i]){ ret = max(ret, max(g[x][i], g[y][i])); x = f[x][i]; y = f[y][i]; } } ret = max(ret, max(g[x][0], g[y][0])); return ret; } int main() { n = read(); m = read(); int T = read(); for(int i = 1; i <= n; i ++) head[i] = -1, p[i] = i; for(int i = 1; i <= m; i ++) S[i].u = read(), S[i].v = read(), S[i].w = read(); sort(S + 1, S + m + 1, cmp); Kruskal(); for(int i = 1; i <= n; i ++) if(!deep[i]) make_deep(i, 1);//可能会有多块 make_jump(); while(T --){ int x = read(), y = read(); int answer = lca(x, y); printf("%d\n", answer); } return 0; }