LCA模板题(在线加离线)
来源:互联网 发布:2017淘宝数据魔方 编辑:程序博客网 时间:2024/06/15 10:57
How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15241 Accepted Submission(s): 5772
Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this “How far is it if I want to go from house A to house B”? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path(“simple” means you can’t visit a place twice) between every two houses. Yout task is to answer all these curious people.
Input
First line is a single integer T(T<=10), indicating the number of test cases.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 4e4 + 10;int n,m;int head[maxn];bool visit[maxn];ll dis[maxn];int Index[10*maxn];int First[maxn];int depth[maxn];int dp[10*maxn][25];int Log[2*maxn];int res;int root;int cnt;struct edge{ int u; int v; ll w; int last;}Edge[2*maxn];void add(int u,int v,ll w){ Edge[cnt].u = u; Edge[cnt].v = v; Edge[cnt].w = w; Edge[cnt].last = head[u]; head[u] = cnt++;}void init(){ root = 1; dis[root] = 0; cnt = 0; res = 1; memset(visit,false,sizeof(visit)); memset(head,-1,sizeof(head)); memset(dis,0,sizeof(dis));}void initRmq(){ Log[0] = -1; for(int i = 1; i < res; i++) { Log[i] = (i&(i - 1)) == 0?Log[i - 1] + 1:Log[i - 1]; } for(int i = 1; i < res; i++) { dp[i][0] = Index[i]; } for(int j = 1; j < 20; j++) { for(int i = 1; i < res&&(i + (1<<j) - 1) < res; i++) { dp[i][j] = (depth[dp[i][j - 1]] < depth[dp[i + (1<<(j - 1))][j - 1]])?dp[i][j - 1]:dp[i + (1<<(j - 1))][j - 1]; } }}int Rmq(int l,int r){ int dis = r - l + 1; int j = Log[dis]; int result = (depth[dp[l][j]] < depth[dp[r - (1<<j) + 1][j]])?dp[l][j]:dp[r - (1<<j) + 1][j]; return result;}void dfs(int root){ if(visit[root]) return; visit[root] = true; for(int i = head[root]; i != -1; i = Edge[i].last) { int v = Edge[i].v; ll w = Edge[i].w; if(!visit[v]) { dis[v] = dis[root] + w; dfs(v); } }}void LCA(int root,int d){ First[root] = res; depth[root] = d; Index[res++] = root; visit[root] = true; for(int i = head[root]; i != -1; i = Edge[i].last) { int v = Edge[i].v; if(!visit[v]) { LCA(v,d + 1); Index[res++] = root; } }}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); int from,to; ll w; for(int i = 1; i <= n - 1; i++) { scanf("%d%d%lld",&from,&to,&w); add(from,to,w); add(to,from,w); } dfs(root); memset(visit,false,sizeof(visit)); LCA(root,0); initRmq(); for(int i = 1; i <= m; i++) { scanf("%d%d",&from,&to); int f1 = First[from]; int f2 = First[to]; if(f1 > f2) swap(f1,f2); int lca = Rmq(f1,f2); ll ans = dis[from] + dis[to] - 2*dis[lca]; printf("%lld\n",ans); } } return 0;}
离线算法:
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 4e4 + 10;int n,m;int head[maxn];bool visit[maxn];ll dis[maxn];int father[maxn];int root;int cnt;struct ask{ int u; int v; int lca;}ask[300];struct edge{ int u; int v; ll w; int last;}Edge[2*maxn];void add(int u,int v,ll w){ Edge[cnt].u = u; Edge[cnt].v = v; Edge[cnt].w = w; Edge[cnt].last = head[u]; head[u] = cnt++;}int Find(int x){ if(x == father[x]) return x; else return father[x] = Find(father[x]);}void init(){ root = 1; dis[root] = 0; cnt = 0; memset(visit,false,sizeof(visit)); memset(head,-1,sizeof(head)); memset(dis,0,sizeof(dis)); for(int i = 1; i <= n; i++) { father[i] = i; }}void dfs(int root){ if(visit[root]) return; visit[root] = true; for(int i = head[root]; i != -1; i = Edge[i].last) { int v = Edge[i].v; ll w = Edge[i].w; if(!visit[v]) { dis[v] = dis[root] + w; dfs(v); } }}void LCA(int root){ for(int i = 1; i <= m; i++) { int u = ask[i].u; int v = ask[i].v; if(root == u) { if(visit[v]) { ask[i].lca = Find(v); } } else if(root == v) { if(visit[u]) { ask[i].lca = Find(u); } } } visit[root] = true; for(int i = head[root]; i != -1; i = Edge[i].last) { int v = Edge[i].v; if(!visit[v]) { LCA(v); father[v] = root; } }}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); int from,to; ll w; for(int i = 1; i <= n - 1; i++) { scanf("%d%d%lld",&from,&to,&w); add(from,to,w); add(to,from,w); } for(int i = 1; i <= m; i++) { scanf("%d%d",&from,&to); ask[i].u = from; ask[i].v = to; } dfs(root); memset(visit,false,sizeof(visit)); LCA(1); for(int i = 1; i <= m; i++) { int lca = ask[i].lca; int u = ask[i].u; int v = ask[i].v; ll ans = dis[u] + dis[v] - 2*dis[lca]; printf("%lld\n",ans); } } return 0;}
- LCA模板题(在线加离线)
- LCA离线+在线+hdu2586(模板)
- LCA算法模板(离线算法,在线算法)
- hdu 2586 LCA模板题(离线和在线两种解法)
- LCA最近公共祖先 在线算法和离线算法 模板
- POJ1330(LCA离线和在线)
- (开坑)在线/离线求lca
- poj 1330lca模板题离线算法
- lca离线算法模板(poj1330验证)
- 离线求lca模板
- lca 离线模板
- lca 离线tarjan模板
- 在线lca算法模板
- lca 在线模板讲解
- LCA离线模板(Tarjan)倍增模板 hdu2586
- 最近公共祖先(LCA):离线&在线算法
- POJ 1986 Distance Queries(LCA在线和离线)
- hdu 2586 How far away ?(在线LCA+离线Tarjan)
- JavaWeb 入门级项目实战 -- 文章发布系统 (第十节)
- 小小C语言之数组与字符串
- 使用极大似然法对逻辑回归中的参数进行估计的数学原理
- iOS 如何选择delegate、notification、KVO?
- C#删除文件夹下的文件
- LCA模板题(在线加离线)
- Retrofit工具类(Retrofit二次封装)
- tomcat开启与配置ssi
- Mac上制作Linux U盘启动盘记录
- SLF 的锁屏密码(DFS枚举,DP)(每个元素 加 或 减 两种选择,求组成特定结果的种数)
- Python_mkdir -p
- miui 安装app闪退问题
- mysql基础:6、mysql创建主键和索引
- C++中lib和dll解析