Mock test when the search, the result is ugly, no points
Down to chew the puzzle, found to use a thing called multiplication, have not learned. But the teacher said, there is no that thing, write violence also has 30~40 points ...
I think the largest spanning tree is still well understood, because we are asking for the path between any two points in the graph, so that the minimum value of the edge is as large as possible. Therefore, the maximum spanning tree is first asked.
When we get the maximum spanning tree, we ask for the minimum value of the edge between the two points, and we can first find their common ancestor. Here is a very detailed code, and note the various writing of the score http://blog.csdn.net/gengmingrui/article/details/47414315
Find out the methods of the recent public ancestors can be doubled, here are detailed introduction, I think it is well written http://blog.sina.com.cn/s/blog_963453200101k6up.html
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #define MAXN 10005using namespace Std;int n,m;struct t{int v; int W; int next;} EDGE[100005]; struct p{int u; int V; int W;} A[maxn*5];bool cmp (P x,p y) {return x.w > y.w;} int head[maxn],cnt;int f[maxn];int find (int x)//and check set to determine if within the same set { if (f[x] = = x) return f[x]; else return f[x] = find (F[x]);} void Add_edge (int u,int v,int W)//tree Edge {edge[cnt].v = v; EDGE[CNT].W = W; Edge[cnt].next = Head[u]; Head[u] = cnt++;} void Union (int u,int v)//Unicom block {int x = find (u); int y = find (v); if (x! = y) f[x] = y;} void Kruskal ()//maximum spanning tree {for (int i = 0; I <= maxn; i++) f[i] = i; for (int i = 1; I <= m; i++) {int u = a[i].u,v = A[I].V; if (Find (u)! = Find (v)) {Union (u,v); Add_edge (U,V,A[I].W); Add_edge (V,U,A[I].W); }}} int up[maxn][25],g[maxn][25],h[maxn];//up[i][j] represents the first 2^j ancestor of I, g[i][j] represents the minimum weight on the 2^j ancestor path I to I, h[i] means I in the tree depth bool vis[maxn];void build_tree (int u) {vis[u] = 1; for (int i = head[u]; i =-1; i = edge[i].next) {int v = EDGE[I].V; if (!vis[v]) {g[v][0] = EDGE[I].W; Up[v][0] = u; H[V] = h[u]+1; Build_tree (v); }}//a darker point upwards and records him to the ancestral edge of the minimum value, with one of his ancestors instead of his int move (int &u,int H) {int res = 123546789; for (int i =20; I >= 0; i--) {if (H[up[u][i]] >= h) {res = min (res,g[u][i]); U = up[u][i]; }} return res;} int query (int u,int v)//self-think is the hardest place {if (Find (u)! = Find (v)) return-1; int res = 123456789; if (h[u]! = H[v]) res = H[u] > h[v]?move (u,h[v]): Move (V,h[u]); if (U = = v) return res; for (int i = +; I >= 0; i--)//multiply record minimum at the same time, two points getting closer to common ancestor {if (up[u][i]! = Up[v][i]) {res = mi N (res,min (g[u][i],g[v][i])); U = up[u][i]; v = up[v][i]; }} res = min (Res,min (g[u][0],g[v][0]));//actually to this step up[x][0] = = Up[y][0] because they are already in the same subtrees tree inside//printf ("up[u][0]:%d\n", up[u][0]); printf ("up[v][0]:%d\n", up[v][0]); return res;} int main () {memset (head,-1,sizeof head); scanf ("%d%d", &n,&m); for (int i = 1; I <= m; i++) scanf ("%d%d%d", &A[I].U,&A[I].V,&A[I].W); Sort (a+1,a+m+1,cmp); Kruskal (); for (int i = 1; I <= n; i++)//build forest and initialize H,up,g {if (!vis[i]) {h[i] = 0; Build_tree (i); G[i][0] = 123456789; Up[i][0] = i; }} for (int i = 1; i <=; i++)//pre-processing up and g,i are too big to affect {for (int j = 1; J <= N; j + +) { Up[j][i] = up[up[j][i-1]][i-1]; G[j][i] = min (g[j][i-1],g[up[j][i-1]][i-1]); }} int q; scanf ("%d", &q); for (int i = 1; I <= Q; i++) {int x, y; scanf ("%d%d", &x,&y); printf ("%d\n", query (x, y)); } return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
NOIP2013 Truck Transport (maximum spanning tree +lca)