LCA(最近公共祖先)模板
2017-07-29 19:00
435 查看
Tarjan版本
倍增版本
/* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000") #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<cstring> #include<queue> #include<set> #include<string> #include<map> #include <time.h> #define PI acos(-1) using namespace std; typedef long long ll; typedef double db; const int maxn = 1e5+5; const ll maxm = 1e7; const ll base = 2333; const int INF = 1<<30; const db eps = 1e-8; const ll mod = 1e9+7; struct Edge{ int u, v, next, val; }edge[maxn*2], edge1[maxn*2]; int n, m; int head[maxn], head1[maxn]; int father[maxn], dis[maxn], tol, toll, LCA[maxn]; bool visit[maxn]; int cnt; //LCA[]最近公共祖先 void init() { cnt=0; memset(head, -1, sizeof(head)); memset(head1, -1, sizeof(head1)); tol=toll=0; memset(visit, 0, sizeof(visit)); memset(LCA, 0, sizeof(LCA)); memset(dis, 0, sizeof(dis)); } void add(int u, int v, int w) { edge[tol].u=u, edge[tol].v=v,edge[tol].val=w; edge[tol].next=head[u]; head[u]=tol++; } void add1(int u, int v, int w) { edge1[toll].u=u, edge1[toll].v=v,edge1[toll].val=w; edge1[toll].next=head1[u]; head1[u]=toll++; } int Find(int x) { if (x!=father[x]) father[x]=Find(father[x]); return father[x]; } void tarjan(int u) { visit[u]=1; father[u]=u; for (int j=head1[u]; ~j; j=edge1[j].next) { int v=edge1[j].v; if (visit[v]) LCA[edge1[j].val]=Find(v); } for (int j=head[u]; ~j; j=edge[j].next) { int v=edge[j].v; if (!visit[v]) { dis[v]=dis[u]+edge[j].val; tarjan(v); father[v]=u; //cout<<dis[v]<<endl; } } } void solve() { init(); scanf("%d%d", &n, &m); for (int i=1; i<n; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); add(b, a, c); } for (int i=0; i<m; i++) { int a, b; scanf("%d%d", &a, &b); add1(a, b, i); add1(b, a, i); } dis[1]=0; tarjan(1); for(int i=0;i<toll;i+=2){ printf("%d\n",LCA[edge1[i].val]); } } int main() { int t = 1; //freopen("in.txt","r",stdin); // freopen("gcd.out","w",stdout); scanf("%d", &t); while(t--) solve(); return 0; }
倍增版本
/* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000") #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<stack> #include<cstring> #include<queue> #include<set> #include<string> #include<map> #include <time.h> #define PI acos(-1) using namespace std; typedef long long ll; typedef double db; const int maxn = 1e5+5; const ll maxm = 1e7; const ll base = 2333; const int INF = 1<<30; const db eps = 1e-8; const ll mod = 1e9+7; struct Edge{ int u, v, next, val; }edge[maxn*2]; int head[maxn], dis[maxn]; int f[maxn], deep[maxn], p[maxn][20]; int n, m, cnt; void init() { int i,j; for(j=0;(1<<j)<=n;j++) for(i=1;i<=n;i++) p[i][j]=-1; for(i=1;i<=n;i++)p[i][0]=f[i]; for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) if(p[i][j-1]!=-1) p[i][j]=p[p[i][j-1]][j-1];//i的第2^j祖先就是i的第2^(j-1)祖先的第2^(j-1)祖先 } void add(int u, int v, int w) { edge[cnt].u=u, edge[cnt].v=v; edge[cnt].next=head[u], edge[cnt].val=w; head[u]=cnt++; } void dfs(int u, int pre, int t) { deep[u]=t; f[u]=pre; for (int i=head[u]; ~i; i=edge[i].next) { int v=edge[i].v; if (v!=pre) { dis[v]=dis[u]+edge[i].val; dfs(v, u, t+1); } } } int lca(int a, int b) { int i, j; if (deep[a]<deep[b]) swap(a, b); for ( i=0; (1<<i)<=deep[a]; i++); i--; for ( j=i; j>=0; j--) { if (deep[a]-(1<<j)>=deep[b]) a=p[a][j]; } if (a==b) return a; for ( j=i; j>=0; j--) { if (p[a][j]!=-1 && p[a][j]!=p[b][j]) { a=p[a][j], b=p[b][j]; } } return f[a]; } void solve() { scanf("%d%d", &n, &m); cnt=0; memset(head, -1, sizeof(head)); for (int i=0; i<n-1; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); add(b, a, c); } dis[1]=0; dfs(1, -1, 0); init(); for (int i=0; i<m; i++) { int a, b; scanf("%d%d", &a, &b); int ans=dis[a]+dis[b]-2*dis[lca(a, b)]; printf("%d\n", ans); } } int main() { int t = 1; // freopen("in.txt","r",stdin); // freopen("gcd.out","w",stdout); scanf("%d", &t); while(t--) solve(); return 0; }
相关文章推荐
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(最近公共祖先)
- 洛谷 P3379 【模板】最近公共祖先(LCA)
- 洛谷 P 3379 【模板】最近公共祖先(LCA)
- 最近公共祖先LCA模板(Tarjan/RMQ)
- 【模板】最近公共祖先(LCA)
- 洛谷——P3379 【模板】最近公共祖先(LCA)
- 【讲解+模板】最近公共祖先(LCA)(倍增)
- 洛谷 P 3379 【模板】最近公共祖先(LCA)
- 洛谷P3379 【模板】最近公共祖先(LCA)
- (倍增)最近公共祖先(LCA)模板
- 洛谷3379 【模板】最近公共祖先(LCA)
- 求LCA最近公共祖先的在线倍增算法模板_C++
- 最近公共祖先LCA【模板】
- [Luogu P3379]【模板】最近公共祖先(LCA)
- 算法模板之最近公共祖先问题(LCA)
- LCA 最近公共祖先 (笔记、模板)
- 洛谷 P3379 【模板】最近公共祖先(LCA)
- 树剖——【模板】最近公共祖先(LCA)
- 【模板】【图论】最近公共祖先(LCA)
- 【模板】最近公共祖先(LCA)