UVA 11354 Bond(最小生成树+lca+倍增求祖先节点)

来源:互联网 发布:vb.net加载dll 编辑:程序博客网 时间:2024/05/01 16:42

题意:n个点m条边,每条边有一个权值,有q个询问,每次询问两点间的一条路径,使得这条路径上权值最大的边最小。

思路:很容易想到最小瓶颈路,但是查询太多,会超时,可以预处理出最小生成树,则问题转化为一棵树上的两点间路径中权值最大的那条边,设这两点为u,v,可以得到dist(u,v)=max(dist(u,lca(u,v)),dist(v,lca(v,lca))),其中lca(u,v)表示u和v的最近公共祖先,用倍增的思想预处理出每个结点的2^i的祖先fa[u][i],然后在离线求出lca后顺便计算出答案即可。

#include<cstdio>  #include<cstring>  #include<cmath>  #include<cstdlib>  #include<iostream>  #include<algorithm>  #include<vector>  #include<map>  #include<queue>  #include<stack> #include<string>#include<map> #include<set>#define eps 1e-6 #define LL long long  using namespace std;  const int maxn = 55000;const int maxm = 1000000 + 10000;//const int INF = 0x3f3f3f3f;int n, m, dep[maxn];int pnt[maxn], ans[maxn], fa[maxn][20], dist[maxn][20];vector<int> G[maxn], W[maxn], query[maxn], num[maxn]; int u[maxm], v[maxm], w[maxm], p[maxn], r[maxm];bool cmp(const int i, const int j) {return w[i] < w[j];} int find(int x) {return p[x] == x ? x : p[x] = find(p[x]);}int Kruscal() {int ans = 0;for(int i = 1; i <= n; i++) p[i] = i; //初始化并查集 for(int i = 0; i < m; i++) r[i] = i; //初始化边序号sort(r, r+m, cmp);for(int i = 0; i < m; i++) {int e = r[i]; int x = find(u[e]), y = find(v[e]);if(x != y) {ans += w[e];p[x] = y;G[u[e]].push_back(v[e]); G[v[e]].push_back(u[e]);W[u[e]].push_back(w[e]); W[v[e]].push_back(w[e]);}}return ans;}int solve(int u, int lca) {int d = dep[u] - dep[lca];//if(u==4&&lca==3) cout << dep[u] << " " << dep[lca] << endl;int ans = 0;for(int i = 17; i >= 0; i--) {if((1<<i) <= d) {d -= (1<<i);ans = max(ans, dist[u][i]);//if(u==4&&lca==3) cout << ans << endl;u = fa[u][i];}}return ans;}bool vis[maxn];int find_pnt(int x) {if(x == pnt[x]) return x;return pnt[x] = find_pnt(pnt[x]);}void dfs(int u) {vis[u] = 1; pnt[u] = u;int sz1 = G[u].size();for(int i = 0; i < sz1; i++) {int v = G[u][i];if(vis[v]) continue;dep[v] = dep[u] + 1;fa[v][0] = u;dist[v][0] = W[u][i];for(int j = 1; j <=17; j++) {if(fa[v][j-1]) fa[v][j] = fa[ fa[v][j-1] ][j-1], dist[v][j] = max(dist[v][j-1], dist[ fa[v][j-1] ][j-1]);else break;}dfs(v);pnt[v] = u;}int sz2 = query[u].size();for(int i = 0; i < sz2; i++) {int v = query[u][i];if(vis[v]) {int lca = find_pnt(v); //cout << lca << endl;ans[num[u][i]] = max(solve(u, lca), solve(v, lca));}}} void init() {memset(vis, 0, sizeof(vis));memset(fa, 0, sizeof(fa));for(int i = 1; i <= n; i++) {G[i].clear(); W[i].clear(); query[i].clear(); num[i].clear();}}int main() {//freopen("input.txt", "r", stdin);int kase = 0;while(cin >> n >> m) {if(kase++) puts("");init();for(int i = 0; i < m; i++) {scanf("%d%d%d", &u[i], &v[i], &w[i]);}Kruscal();int q; cin >> q;for(int i = 0; i < q; i++) {int x, y; scanf("%d%d", &x, &y);query[x].push_back(y);query[y].push_back(x);num[x].push_back(i);num[y].push_back(i);}dep[1] = 0;dfs(1);//cout << solve(4, 1) << endl;for(int i = 0; i < q; i++) printf("%d\n", ans[i]);} return 0;}

0 0
原创粉丝点击