1. 程式人生 > >NOIP 2013 貨車運輸

NOIP 2013 貨車運輸

tin lse lan swap get size 最小邊 != tps

題目鏈接

https://www.luogu.org/problemnew/show/P1967

一眼看出思路,20分鐘敲代碼,40分鐘調試

一個小時一次提交AC了這道題

首先有個結論

最大生成樹上兩兩之間的路徑一定是最大的,如果存在不是,那麽這顆樹就不是最大生成樹

然後就樹上倍增求最小邊權就好了

然後以後根節點的父親可以設為0,然後一開始跳到同一深度的時候特判一下就好了

然後註意一些細節,寫在程序裏面了

#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define
_for(i, a, b) for(register int i = (a); i <= (b); i++) using namespace std; const int MAXN = 5e4 + 10; const int MAXM = 20; struct Edge{ int to, w, next; }; Edge e[MAXN << 1]; int head[MAXN], tot; int F[MAXN][MAXM + 5], data[MAXN][MAXM + 5]; //註意這裏MAXM+5 int f[MAXN], vis[MAXN], d[MAXN], n, m;
struct node { int u, v, w; bool operator < (const node& rhs) const { return w > rhs.w; } }; vector<node> edges; void AddEdge(int from, int to, int w) { e[tot] = Edge{to, w, head[from]}; head[from] = tot++; } void read(int& x) {
int f = 1; x = 0; char ch = getchar(); while(!isdigit(ch)) { if(ch == -) f = -1; ch = getchar(); } while(isdigit(ch)) { x = x * 10 + ch - 0; ch = getchar(); } x *= f; } int find(int x) { if(f[x] == x) return x; return f[x] = find(f[x]); } void dfs(int u) { vis[u] = 1; for(int i = head[u]; ~i; i = e[i].next) { int v = e[i].to; if(vis[v]) continue; //註意這裏直接continue d[v] = d[u] + 1; //先算d再遞歸下去 dfs(v); F[v][0] = u; data[v][0] = e[i].w; } } int min_val(int u, int v) { int res = 1e9; if(d[u] < d[v]) swap(u, v); for(int j = MAXM; j >= 0; j--) if(F[u][j] && d[F[u][j]] >= d[v]) //註意這裏要特判0 { res = min(res, data[u][j]); //註意這裏一定是先統計再跳 u = F[u][j]; } if(u == v) return res; for(int j = MAXM; j >= 0; j--) if(F[u][j] != F[v][j]) { res = min(res, min(data[u][j], data[v][j])); u = F[u][j]; v = F[v][j]; } return min(res, min(data[u][0], data[v][0])); } int main() { memset(head, -1, sizeof(head)); tot = 0; read(n); read(m); _for(i, 1, m) { int u, v, w; read(u); read(v), read(w); edges.push_back(node{u, v, w}); } sort(edges.begin(), edges.end()); _for(i, 1, n) f[i] = i; REP(i, 0, edges.size()) { int u = edges[i].u, v = edges[i].v, w = edges[i].w; int fu = find(u), fv = find(v); if(fu != fv) { f[fu] = fv; AddEdge(u, v, w); AddEdge(v, u, w); } } _for(u, 1, n) if(!vis[u]) { F[u][0] = 0; //這裏把每個根的父親設為0,在倍增的時候需要特判0 dfs(u); } _for(j, 1, MAXM) _for(u, 1, n) { F[u][j] = F[F[u][j-1]][j-1]; data[u][j] = min(data[u][j-1], data[F[u][j-1]][j-1]); } int q; read(q); while(q--) { int u, v; read(u); read(v); if(find(u) != find(v)) puts("-1"); else printf("%d\n", min_val(u, v)); } return 0; }

NOIP 2013 貨車運輸