• 51nod2621 树上距离一题四解ST表+倍增+Tarjan+树剖


    LCA裸题 只有代码无原理,给自己复习用

    1. ST表(这题2^10就够了)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=2e3+50;
     5 
     6 int cnt,dfn[maxn],dep[maxn],dp[maxn][21],lg2[maxn],dis[maxn],w[maxn][maxn];
     7 std::vector<int> G[maxn];
     8 void dfs(int u,int fa){
     9     dis[u]=dis[fa]+w[u][fa];
    10     dfn[u]=++cnt; dep[u]=dep[fa]+1; dp[cnt][0]=u;
    11     for(int i=0,v;i<G[u].size();i++){
    12         if((v=G[u][i])==fa) continue;
    13         dfs(v,u);
    14         dp[++cnt][0]=u;
    15     }
    16 }
    17 void st(){
    18     for(int i=2;i<=cnt;i++) lg2[i]=lg2[i>>1]+1;
    19     for(int j=1;j<=20;j++){
    20         for(int i=1;i+(1<<j)-1<=cnt;i++){
    21             int r=i+(1<<(j-1));
    22             dp[i][j] = dep[dp[i][j - 1]] < dep[dp[r][j - 1]] ? dp[i][j - 1] : dp[r][j - 1];
    23         }
    24     }
    25 }
    26 int que(int l,int r){
    27     if(l>r) swap(l,r);
    28     int k=lg2[r-l+1];
    29     return dep[dp[l][k]] < dep[dp[r - (1 << k) + 1][k]] ? dp[l][k] : dp[r - (1 << k) + 1][k];
    30 }
    31 int main(){
    32     int n,q; cin>>n>>q;
    33     for(int i=1;i<n;i++){
    34         int u,v,we; cin>>u>>v>>we;
    35         G[u].push_back(v);
    36         G[v].push_back(u);
    37         w[u][v]=w[v][u]=we;
    38     }
    39     dfs(1,0); st();
    40     for(int i=0;i<q;i++){
    41         int u,v; cin>>u>>v;
    42         printf("%d
    ",dis[u]+dis[v]-2*dis[que(dfn[u],dfn[v])]);
    43     }
    44     return 0;
    45 }

    2. 倍增

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=2e3+50;
     5 vector<int> G[maxn];
     6 int dep[maxn],fa[maxn][13],dis[maxn],w[maxn][maxn],lim=11;
     7 void dfs(int u,int rt){
     8     dep[u]=dep[rt]+1; fa[u][0]=rt; dis[u]=dis[rt]+w[rt][u];
     9     for(int i=1;i<lim;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    10     for(int i=0;i<G[u].size();i++){
    11         int v=G[u][i]; if(v!=rt) dfs(v,u);
    12     }
    13 }
    14 
    15 int LCA(int x,int y){
    16     if(dep[x]<dep[y]) swap(x,y);//x更深
    17     for(int i=lim-1;~i;i--)//x上移
    18         if(dep[x]-(1<<i)>=dep[y]) x=fa[x][i];
    19     if(x==y) return x;
    20     for(int i=lim-1;~i;i--)
    21         if(fa[x][i]!=fa[y][i])
    22             x=fa[x][i], y=fa[y][i];
    23     return fa[x][0];
    24 }
    25 int main(){
    26     ios::sync_with_stdio(0);
    27     cin.tie(0); cout.tie(0);
    28     int n,q; cin>>n>>q;
    29     for(int i=1;i<n;i++){
    30         int u,v,we; cin>>u>>v>>we;
    31         G[u].push_back(v);
    32         G[v].push_back(u);
    33         w[u][v]=w[v][u]=we;
    34     }
    35     dfs(1,0);
    36     for(int i=0;i<q;i++){
    37         int u,v; cin>>u>>v;
    38         int lca=LCA(u,v);
    39         cout<<dis[u]+dis[v]-2*dis[lca]<<endl;
    40     }
    41     
    42     return 0;
    43 }

    3. tarjan

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=2e3+50;
     5 struct node{ int next,to; }edge[maxn];
     6 int head[maxn],cnt;
     7 void add(int u,int v){
     8     edge[++cnt].to = v;
     9     edge[cnt].next = head[u];
    10     head[u] = cnt;
    11 }
    12 
    13 struct node2{ int id,to,next; }que[maxn];
    14 int qhead[maxn],cnt2;
    15 void add_q(int u,int v,int i){
    16     que[++cnt2].to = v;
    17     que[cnt2].id = i;
    18     que[cnt2].next = qhead[u];
    19     qhead[u] = cnt2;
    20 }
    21 
    22 int fa[maxn],lca[maxn],w[maxn][maxn],dis[maxn],ans[maxn];
    23 bool vis[maxn];
    24 
    25 int findd(int x){ return x==fa[x]?x:fa[x]=findd(fa[x]); }
    26 
    27 void tarjan(int u){
    28     vis[u] = 1;
    29     for(int i = head[u];i;i = edge[i].next){
    30         int v = edge[i].to; if(v==u) continue;
    31         if(!vis[v]){                                        //如果没有被访问过,就tagjan这个点
    32             dis[v]=dis[u]+w[u][v];
    33             tarjan(v);
    34             fa[v] =findd(u);
    35         }
    36     }
    37     for(int i = qhead[u];i;i = que[i].next){
    38         int v = que[i].to; if(v==u) continue;
    39         if(vis[v]){                                          //找答案时,已经访问过的节点就可以记录lca了
    40             lca[que[i].id] = findd(v);
    41             ans[que[i].id]=dis[u]+dis[v]-2*dis[lca[que[i].id]];        
    42            }
    43     }
    44 }
    45 int rt[maxn];
    46 int main(){
    47     int n,m; cin >> n >> m ;
    48     int a,b,we;
    49     for(int i = 1;i < n;i ++){
    50         cin >> a >> b>>we;
    51         add(a,b);
    52         add(b,a);
    53         w[a][b]=w[b][a]=we;
    54     }
    55     for(int i = 1;i <= m;i ++){
    56         cin >> a >> b;
    57         add_q(a,b,i);
    58         add_q(b,a,i);
    59     }
    60     for(int i = 1;i <= n;i ++) fa[i] = i;
    61     tarjan(1);
    62     for(int i = 1;i <= m;i ++){ cout<<ans[i]<<endl; }
    63     return 0;
    64 }

    4. 树剖

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=2e3+50;
     5 int cnt, size[maxn], f[maxn], dep[maxn], dis[maxn], w[maxn][maxn], son[maxn], top[maxn];
     6 std::vector<int> G[maxn];
     7 void dfs1(int u,int fa){
     8     size[u]=1; dep[u]=dep[fa]+1; f[u]=fa;
     9     dis[u]=dis[fa]+w[fa][u];
    10     for(int i=0;i<G[u].size();i++){
    11         int v=G[u][i]; if(v==fa) continue;
    12         dfs1(v,u);
    13         size[u]+=size[v];
    14         if(size[v]>size[son[u]]) son[u]=v;
    15     }
    16 }
    17 
    18 void dfs2(int u,int t){
    19     top[u]=t;
    20     if(son[u]) dfs2(son[u],t);
    21     for(int i=0;i<G[u].size();i++){
    22         int v=G[u][i];
    23         if(v!=f[u]&&v!=son[u]) dfs2(v,v);
    24     }
    25 }
    26 
    27 int LCA(int x,int y){
    28     while(top[x]!=top[y]){
    29         if(dep[top[x]]>dep[top[y]]) x=f[top[x]];
    30         else y=f[top[y]];
    31     }
    32     return dep[x]<dep[y]? x: y;
    33 }
    34 int main(){
    35     ios::sync_with_stdio(0);
    36     cin.tie(0); cout.tie(0);
    37     int n,q; cin>>n>>q;
    38     for(int i=1;i<n;i++){
    39         int u,v,we; cin>>u>>v>>we;
    40         G[u].push_back(v);
    41         G[v].push_back(u);
    42         w[u][v]=w[v][u]=we;
    43     }
    44     dfs1(1,1); dfs2(1,1);
    45     for(int i=0;i<q;i++){
    46         int u,v; cin>>u>>v;
    47         int lca=LCA(u,v);
    48         cout<<dis[u]+dis[v]-2*dis[lca]<<endl;
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    甘草
    html2pdf
    gitlab jenkins 安装笔记
    mac phpbrew安装
    域名解析各项记录对应的值
    网站添加ico图标
    dom控制
    webstrom 代码工具(转http://www.cnblogs.com/tangdanni11/p/5149063.html)
    http协议(转http://www.cnblogs.com/guguli/p/4758937.html)
    预解析机制
  • 原文地址:https://www.cnblogs.com/noobimp/p/12001114.html
Copyright © 2020-2023  润新知