(題目總結)LCA板子以及一些題目
阿新 • • 發佈:2019-04-15
style 更新 not tro nec 技術分享 har read conn
---恢復內容開始---
LCA算法總結
把lca題目記入下來!分享給你們
板子tarjan(離線)
#define N 10005 #define M 1000005 // N 表示的樹的節點 // M 表示的問題數 int cnt_e,cnt_q,head_e[N],head_q[N],vis[N],dis[N],t,ans[M],id[N],f[N]; // 邊,問題數 struct node{ int u,w,next; }e[N*2],q[M*2]; void init(){ memset(head_e,-1,sizeof(head_e)); memset(head_q,View Code-1,sizeof(head_q)); memset(vis,0,sizeof(vis)); cnt_e=0; cnt_q=0; } void addedge(int x,int y,int z){ e[cnt_e].u=x;e[cnt_e].w=z;e[cnt_e].next=head_e[y];head_e[y]=cnt_e++; e[cnt_e].u=y;e[cnt_e].w=z;e[cnt_e].next=head_e[x];head_e[x]=cnt_e++; } void addquery(int x,int y,int z){ q[cnt_q].u=x;q[cnt_q].w=z;q[cnt_q].next=head_q[y];head_q[y]=cnt_q++; q[cnt_q].u=y;q[cnt_q].w=z;q[cnt_q].next=head_q[x];head_q[x]=cnt_q++; } int find(int x){ if(f[x] == x) return x; else return f[x] = find(f[x]); } void tarjan(int k){ f[k]=k; vis[k]=1; id[k]=t;int i,v; for(i=head_q[k];i!=-1;i=q[i].next){ v=q[i].u; if(vis[v]){ // 表示的就是一顆樹 // 每次只需要在這裏做文章就行 // ans[q[i].w] = find(v); //求的是lca //ans[q[i].w]=dis[k]+dis[v]-2*dis[find(v)]; //求的是兩個點的距離 // solve1() 可以表示的是森林 //可以去求這個森林 if(id[v] == id[k]) //ans[q[i].w] = find(v); ans[q[i].w] = dis[k]+dis[v]-2*dis[find(v)]; else ans[q[i].w]=-1; } } for(i=head_e[k];i!=-1;i=e[i].next){ v=e[i].u; if(!vis[v]){ dis[v]=dis[k]+e[i].w; tarjan(v); f[v]=k; } } }
LCA第一題:
給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先
題意:-------
我的理解:
直接套板子(因為是一顆樹!直接套solve2)
AC 代碼
#include<bits/stdc++.h> #include<iostream> #include<algorithm> #include<cmath> #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<string> #include<set> typedef long long int ll; using namespace std; void read(int &x){ int f=1;x=0;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} x*=f; } #define N 500005 #define M 1000005 // N 表示的樹的節點 // M 表示的問題數 int cnt_e,cnt_q,head_e[N],head_q[N],vis[N],dis[N],t,ans[M],id[N],f[N]; // 邊,問題數 struct node{ int u,w,next; }e[N*2],q[M*2]; void init(){ memset(head_e,-1,sizeof(head_e)); memset(head_q,-1,sizeof(head_q)); memset(vis,0,sizeof(vis)); cnt_e=0; cnt_q=0; } void addedge(int x,int y,int z){ e[cnt_e].u=x;e[cnt_e].w=z;e[cnt_e].next=head_e[y];head_e[y]=cnt_e++; e[cnt_e].u=y;e[cnt_e].w=z;e[cnt_e].next=head_e[x];head_e[x]=cnt_e++; } void addquery(int x,int y,int z){ q[cnt_q].u=x;q[cnt_q].w=z;q[cnt_q].next=head_q[y];head_q[y]=cnt_q++; q[cnt_q].u=y;q[cnt_q].w=z;q[cnt_q].next=head_q[x];head_q[x]=cnt_q++; } int find(int x){ if(f[x] == x) return x; else return f[x] = find(f[x]); } void tarjan(int k){ f[k]=k; vis[k]=1; id[k]=t; int i,v; for(i=head_q[k];i!=-1;i=q[i].next){ v=q[i].u; if(vis[v]){ // 表示的就是一顆樹 // 每次只需要在這裏做文章就行 ans[q[i].w] = find(v); //求的是lca //ans[q[i].w]=dis[k]+dis[v]-2*dis[find(v)]; //求的是兩個點的距離 // solve1() 可以表示的是森林 //可以去求這個森林 /* //ans[q[i].w] = find(v); ans[q[i].w] = dis[k]+dis[v]-2*dis[find(v)]; else ans[q[i].w]=-1; */ } } for(i=head_e[k];i!=-1;i=e[i].next){ v=e[i].u; if(!vis[v]){ dis[v]=dis[k]+e[i].w; tarjan(v); f[v]=k; } } } void solve1(){ int n, m, cc, root, x, y, z; while(scanf("%d%d%d",&n,&cc,&m) == 3){ init(); while(cc--){ //scanf("%d%d%d",&x,&y,&z); read(x),read(y),read(z); //z = 1; addedge(x,y,z); } for(int i = 0;i < m; i++){ read(x),read(y); //scanf("%d%d",&x,&y); addquery(x,y,i); } t = 0; // 這個是全局的變量 for(int i = 1; i <= n; i++, t++){ if(!vis[i]){ dis[i] = 0; tarjan(i); } } for(int i = 0; i < m; i++){ if(ans[i] == -1){ // 表示的就是不在一顆樹 puts("Not connected"); }else printf("%d\n",ans[i]); } } } void solve2(){ // 需要註意的就是這個tarjan 裏面ans換下就可以求一顆樹 int tt ; //read(tt); tt = 1; while(tt--){ int n, m, cc, root, x, y, z; read(n),read(m),read(root); init(); for(int i = 1; i < n; i++){ read(x),read(y); //read(z); z = 1; //scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); } for(int i = 0; i < m; i++){ read(x),read(y); addquery(x,y,i); } // 一顆樹的話,一般root 為1 ///只有一顆樹,t 默認為0 // root = 1; t = 0; dis[root] = 0; tarjan(root); for(int i = 0; i < m; i++){ printf("%d\n",ans[i]); } } } int main(){ int tt; //read(tt); tt = 1; while(tt--){ // 1 表示的就是森林 //solve1(); solve2(); } return 0; }AC
持續更新中
(題目總結)LCA板子以及一些題目