• Tarjan LCA


    强连通
     1269  迷宫城堡
     2767 Proving Equivalences
     3836 Equivalent Sets
     1827 Summer Holiday
     3072 Intelligence System
     3861 The King’s Problem
     3639 Hawk-and-Chicken
     3594 Cactus 仙人掌图
     4685
    [双连通]:
    2242 考研路茫茫——空调教室  双联通缩点+树形DP
    2460 Network 边双连通
    3849 By Recognizing These Guys, We Find Social Networks Useful  双连通求桥
    3896 Greatest TC  双连通
    4005 The war  边双连通
    3394 Railway 双连通求块
    
    [LCA]:
    2586 How far away ?
    2874 Connections between cities
    3078 Network  
    3830 Checkers 
    4338 Simple Path 

    参考Vendetta

         需要补充的是vis可以在访问到节点时就标记,也可以在访问完其子孙后再标记,区别在于前者可以查询a和b的关系以及b和a的关系,而后者只能查询b和a的关系(假设先访问a),但既然是无向图,答案是一样的,目测放前面可能更强大。

     

    HDU2586
    #include<cstdio> #include<cstring> #include<cstring> #include<iostream> int const MAX = 40005; struct Edge { int id, val; int next; }e[2 * MAX]; int n, m, cnt; int x[MAX], y[MAX], z[MAX]; int fa[MAX], dist[MAX], pre[MAX]; bool vis[MAX]; void _add(int u, int v, int w) { e[cnt].id = u; e[cnt].val = w; e[cnt].next = pre[v]; pre[v] = cnt++; } int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } void tarjan(int k) { vis[k]=true; fa[k]=k; for(int i=pre[k];i;i=e[i].next){ if(!vis[e[i].id]){ dist[e[i].id]=dist[k]+e[i].val; tarjan(e[i].id); fa[e[i].id] = k; } } //vis[k]=true; for(int i=1;i<=m;i++){ if(x[i]==k&&vis[y[i]]) z[i]=Find(y[i]); } } int main() { int T,u,v,w; scanf("%d",&T); while(T--){ scanf("%d %d", &n, &m); cnt=0; memset(pre,0,sizeof(pre)); for(int i=1;i<n;i++){ scanf("%d %d %d",&u,&v,&w); _add(u,v,w); _add(v,u,w); } for(int i=1;i<=n;i++) x[i]=y[i]=z[i]=0; for(int i=1;i<=m;i++) scanf("%d %d",&x[i],&y[i]); memset(vis, false, sizeof(vis)); dist[1] = 0; tarjan(1); for(int i = 1; i <= m; i++) printf("%d ",dist[x[i]] + dist[y[i]] - 2 * dist[z[i]]); } }
    HDU2874
    #include <iostream>
    #include <vector>
    #include <stack>
    #include <cstring>
    #include <cstdio>
    #include <memory.h>
    #include<vector>
    using namespace std;
    int Laxt[10001],Next[20001],To[20001],Len[20001];
    int Laxt2[10001],Next2[2000001],To2[2000001],ans[1000001];
    bool vis[10001];
    int cnt,cnt2;
    int dis[10001],fa[10001];
    void _update()
    {
        memset(Laxt,-1,sizeof(Laxt));
        memset(Laxt2,-1,sizeof(Laxt2));
        memset(vis,false,sizeof(vis));
        cnt=cnt2=0;
    }
    void _add(int u,int v,int d){
        Next[cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        Len[cnt++]=d;
    }
    void _add2(int u,int v){
        Next2[cnt2]=Laxt2[u];
        Laxt2[u]=cnt2;
        To2[cnt2++]=v;
        Next2[cnt2]=Laxt2[v];
        Laxt2[v]=cnt2;
        To2[cnt2++]=u;
    }
    int _findfa(int v){
        if(v==fa[v]) return fa[v];
        return fa[v]=_findfa(fa[v]);
    }
    void _tarjan(int v)
    {
        vis[v]=true;fa[v]=v;
        for(int i=Laxt[v];i!=-1;i=Next[i]){
            if(!vis[To[i]]){
                dis[To[i]]=dis[v]+Len[i];
                _tarjan(To[i]);
                fa[To[i]]=v;
            }
        }
        for(int i=Laxt2[v];i!=-1;i=Next2[i]){
            if(vis[To2[i]]){
                int tmp=_findfa(To2[i]);
                if(dis[To2[i]]!=-1)
                  ans[i/2]=dis[v]+dis[To2[i]]-2*dis[tmp];
            }
        }
    }
    int main()
    { 
        int n,m,c,i,x,y,z;
          while(~scanf("%d %d %d",&n,&m,&c)){
               _update();
               for(i=0;i<m;i++){
                    scanf("%d%d%d",&x,&y,&z);
                    _add(x,y,z);
                    _add(y,x,z);
               }
               for(i=0;i<c;i++){
                    scanf("%d%d",&x,&y);
                    _add2(x,y);
               }
                for(i=1;i<=n;i++){
                    if(!vis[i]){
                      memset(dis,-1,sizeof(dis));
                      dis[i]=0;
                      _tarjan(i);
                    }
                 } 
                   for(i=0;i<c;i++)
                   if(ans[i]==-1) printf("Not connected
    ");
                   else  printf("%d
    ",ans[i]);
          }
          return 0;
    }
  • 相关阅读:
    报表设计器的使用之一:入门
    统计图开发之二:点图元
    统计图开发之一:画法定义
    集算器之五:序表
    集算器之四:程序流程
    忏悔录
    请不要离我而去
    所想和所做 所梦和所成
    做出改变,不断改变。
    Linux 操作命令
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7634270.html
Copyright © 2020-2023  润新知