n个点m条边的带权无向图,S个询问,每次询问L->H的所有路径中,最小边最大的那条路径的最小边。
只要能发现,最优路径必然是kruskal求得的最大生成树上就一切都好办了。求出MST,然后在线LCA搞就行了。
#include<functional> #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<string> #include<queue> #include<map> #include<set> #define REP(i, n) for(int i=0; i<n; i++) #define FF(i, a, b) for(int i=a; i<b; i++) #define FD(i, a, b) for(int i=a; i>=b; i--) #define LL long long #define PB push_back #define MP make_pair #define PII pair<int, int> #define xx first #define yy second #define CLR(a, b) memset(a, b, sizeof(a)) #define debug puts("****debug****") using namespace std; const int maxn = 1e5 + 10; const int INF = 1e9; int n, m, S, l, h; int fa[maxn], pa[maxn], L[maxn], cost[maxn], anc[maxn][100], mincost[maxn][100]; vector<PII> edges; vector<int> G[maxn]; void init() { L[1] = cost[1] = 0; REP(i, n+1) G[i].clear(), pa[i] = i; edges.clear(); } void AddEdge(int u, int v, int w) { edges.PB(MP(v, w)); edges.PB(MP(u, w)); int nc = edges.size(); G[u].PB(nc-2); G[v].PB(nc-1); } struct Edge { int u, v, w; bool operator < (const Edge& rhs) const { return w > rhs.w; } }e[maxn]; int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); } void MST() { sort(e, e+m); int cnt = 0; REP(i, m) { int x = findset(e[i].u), y = findset(e[i].v); if(x != y) { pa[x] = y; cnt++; AddEdge(e[i].u, e[i].v, e[i].w); } if(cnt == n-1) return ; } } void dfs(int u, int f) { fa[u] = f; REP(i, G[u].size()) { int v = edges[G[u][i]].xx, w = edges[G[u][i]].yy; if(v != f) { cost[v] = w; L[v] = L[u] + 1; dfs(v, u); } } } void preprocess() { FF(i, 1, n+1) { anc[i][0] = fa[i], mincost[i][0] = cost[i]; for(int j=1; (1<<j) < n; j++) anc[i][j] = -1; } for(int j=1; (1<<j) < n; j++) FF(i, 1, n+1) if(anc[i][j-1] != -1) { int a = anc[i][j-1]; anc[i][j] = anc[a][j-1]; mincost[i][j] = min(mincost[i][j-1], mincost[a][j-1]); } } int query(int p, int q) { int lo; if(L[p] < L[q]) swap(p, q); for(lo=1; (1<<lo) <= L[p]; lo++); lo--; int ans = INF; FD(i, lo, 0) if(L[p] - (1<<i) >= L[q]) ans = min(ans, mincost[p][i]), p = anc[p][i]; if(p == q) return ans; FD(i, lo, 0) if(anc[p][i] != -1 && anc[p][i] != anc[q][i]) { ans = min(ans, mincost[p][i]), p = anc[p][i]; ans = min(ans, mincost[q][i]), q = anc[q][i]; } ans = min(ans, cost[p]); ans = min(ans, cost[q]); return ans; } int main() { while(~scanf("%d%d%d", &n, &m, &S)) { init(); REP(i, m) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); MST(); dfs(1, -1); preprocess(); while(S--) { scanf("%d%d", &l, &h); printf("%d\n", query(l, h)); } } return 0; }