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
- UVA 11354 Bond(最小生成树+lca+倍增求祖先节点)
- 【UVa】11354 Bond 最小生成树,动态LCA,倍增思想
- UVA 11354 Bond(最小生成树+LCA倍增)
- UVa 11354 Bond 最小生成树+LCA倍增
- UVA - 11354Bond最小生成树,LCA寻找最近公共祖先
- UVA11354[Bond] 倍增求LCA+Kruskal求最小瓶颈生成树
- UVA 11354 Bond 瓶颈路 最小生成树+LCA类似
- UVA 11354 Bond(最小生成树+LCA)
- Uva 11354 Bond(最小生成树+LCA)
- UVA - 11354 Bond(生成树+LCA)
- 最小生成树和倍增法求lca(Uva11354Bond)
- UVA 11354 - Bond (最小生成树 + 树链剖分)
- uva 11354 bond 倍增
- lca倍增 算法 最小公共祖先
- 求二叉树中两个节点的最小公共祖先(LCA)
- 倍增法求最近公共祖先 lca
- UVA 11354 Bond (最小生成树 + 树链剖分)
- UVA 11354 LCA+最小生成树
- 黑马程序员—— Java 基础 面向对象之继承 (复习)
- 堆排序2.0
- POJ2503词典 Babelfish在外文中查找对应的英文
- 子父类中构造函数的特点
- zoj-2112(主席树动态求区间第k小数)
- UVA 11354 Bond(最小生成树+lca+倍增求祖先节点)
- 页面更新的问题
- 一次被黑追凶(未完待续)
- hdoj 1143 Tri Tiling 【递推】
- 链接MapReduce作业http://user.qzone.qq.com/1178772762/blog/1440417746
- Windows内核编程基础篇之字符串的拷贝
- Hbase优化
- 设置异常向量表
- 跟我一起写Makefile:书写规则