首先,每一辆货车路径唯一,说明应该求生成树。又要满足这条路的最小边权最大,进一步得出要求最大生成树。
求完最大生成树上要解决的是树上任意两点之间的边权的最小值,我第一反应是树剖维护链上最小值,但其实我们用LCA就可以了:对于任意两点x, y, 维护x到LCA(x, y)和y到LCA(x, y)这两条链上的最小值。时间复杂度O(nlogn)。
还有几点要注意:
1.图并不连通,所以对于每一个没遍历过的点都要跑一遍LCA。
2.好像没啦。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e5 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, m, q; 38 vector<int> v[maxn], c[maxn]; 39 struct Edge 40 { 41 int x, y, co; 42 bool operator < (const Edge& other)const 43 { 44 return co > other.co; 45 } 46 }e[maxn * 5]; 47 48 int p[maxn]; 49 void init(int n) 50 { 51 for(int i = 1; i <= n; ++i) p[i] = i; 52 } 53 int Find(int x) 54 { 55 return x == p[x] ? x : p[x] = Find(p[x]); 56 } 57 58 bool vis[maxn]; 59 int dep[maxn], fa[maxn][21], Min[maxn][21]; 60 void dfs(int now) 61 { 62 vis[now] = 1; 63 for(int i = 1; (1 << i) <= dep[now]; ++i) 64 { 65 fa[now][i] = fa[fa[now][i - 1]][i - 1]; 66 Min[now][i] = min(Min[now][i - 1], Min[fa[now][i - 1]][i - 1]); 67 } 68 for(int i = 0; i < (int)v[now].size(); ++i) 69 { 70 if(!vis[v[now][i]]) 71 { 72 dep[v[now][i]] = dep[now] + 1; 73 fa[v[now][i]][0] = now; 74 Min[v[now][i]][0] = c[now][i]; 75 dfs(v[now][i]); 76 } 77 } 78 } 79 int lca(int x, int y) 80 { 81 int ret = INF; 82 if(dep[x] < dep[y]) swap(x, y); 83 for(int i = 20; i >= 0; --i) 84 if(dep[x] - (1 << i) >= dep[y]) 85 { 86 if(Min[x][i] != 0) 87 ret = min(ret, Min[x][i]); 88 x = fa[x][i]; 89 } 90 if(x == y) return ret; 91 for(int i = 20; i >= 0; --i) 92 { 93 if(fa[x][i] != fa[y][i]) 94 { 95 ret = min(ret, Min[x][i]); 96 ret = min(ret, Min[y][i]); 97 x = fa[x][i]; y = fa[y][i]; 98 } 99 } 100 return min(ret, min(Min[x][0], Min[y][0])); 101 } 102 103 int main() 104 { 105 n = read(); m = read(); 106 init(n); 107 for(int i = 1; i <= m; ++i) e[i].x = read(), e[i].y = read(), e[i].co = read(); 108 sort(e + 1, e + m + 1); 109 for(int i = 1, cnt = 0; i <= m; ++i) 110 { 111 int px = Find(e[i].x), py = Find(e[i].y); 112 if(px != py) 113 { 114 p[px] = py; 115 v[e[i].x].push_back(e[i].y); c[e[i].x].push_back(e[i].co); 116 v[e[i].y].push_back(e[i].x); c[e[i].y].push_back(e[i].co); 117 if(++cnt == n - 1) break; 118 } 119 } 120 for(int i = 1; i <= n; ++i) if(!vis[i]) dfs(i); 121 q = read(); 122 for(int i = 1; i <= q; ++i) 123 { 124 int x = read(), y = read(); 125 if(Find(x) == Find(y)) write(lca(x, y)), enter; 126 else write(-1), enter; 127 } 128 return 0; 129 }