zoukankan      html  css  js  c++  java
  • 学习LCA( 最近公共祖先·二)

    http://poj.org/problem?id=1986

    离线找u,v之间的最小距离(理解推荐)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    char s[2];
    const int M=1e5+5;
    const int N=2e4+4;
    struct node{
        int v,w,nextt;
    }e[M];
    struct NODE{
        int v,dis,nextt;
    }g[M];
    int fa[M],head[M],Head[M],vis[M],dis[M];
    int tot,TOT;
    void addedge(int u,int v,int w){
        e[tot].v=v;
        e[tot].w=w;
        e[tot].nextt=head[u];
        head[u]=tot++;
        e[tot].v=u;
        e[tot].w=w;
        e[tot].nextt=head[v];
        head[v]=tot++;
    }
    ///存储询问的u,v
    void ADDedge(int u,int v){
        g[TOT].v=v;
        g[TOT].nextt=Head[u];
        Head[u]=TOT++;
        g[TOT].v=u;
        g[TOT].nextt=Head[v];
        Head[v]=TOT++;
    }
    int Find(int x){
        return fa[x]==x?x:fa[x]=Find(fa[x]);
    }
    void LCA(int u){
        fa[u]=u;
        vis[u]=true;
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(!vis[v]){
                dis[v]=dis[u]+e[i].w;
                LCA(v);
                fa[v]=u;
            }
        }
        for(int i=Head[u];~i;i=g[i].nextt){
            int v=g[i].v;
            if(vis[v]){
                g[i].dis=dis[u]+dis[v]-2*dis[Find(v)];
                g[i^1].dis=g[i].dis;
            }
        }
    }
    int main(){
        int n,m;
        memset(head,-1,sizeof(head));
        memset(Head,-1,sizeof(Head));
        scanf("%d%d",&n,&m);
        while(m--){
            int u,v,w;
            scanf("%d%d%d%s",&u,&v,&w,s);
            addedge(u,v,w);
        }
        int k;
        scanf("%d",&k);
        for(int i=0;i<k;i++){
            int  u,v;
            scanf("%d%d",&u,&v);
            ADDedge(u,v);
        }
        LCA(1);
        for(int i=0;i<TOT;i+=2){
            printf("%d
    ",g[i].dis);
        }
        return 0;
    }
    View Code

    http://hihocoder.com/problemset/problem/1067

    tangin+离线

    #include<bits/stdc++.h>
    using namespace std;
    const int M=1e5+10;
    struct node{
        int to,index;
        node (int v,int index){
            this->to=v;
            this->index=index;
        }
    };
    vector<int>graph[M];
    vector<node>e[M];
    bool sign[M];
    map<int,string>str;
    map<string,int>indx;
    int ans[M];
    
    int f[M],color[M];
    int tot,n,m,root;
    void init(){
        tot=0;
        indx.clear();
        memset(sign,false,sizeof(sign));
        memset(color,0,sizeof(color));
        memset(ans,0,sizeof(ans));
        for(int i=0;i<M;i++){
            graph[i].clear();
            e[i].clear();
            f[i]=i;
        }
    }
    int find(int x){
        return x==f[x]?x:f[x]=find(f[x]);
    }
    int get_index(string x){
        if(indx.count(x))
            return indx[x];
        indx[x]=++tot;
        str[tot]=x;
        return tot;
    }
    void input(){
        cin>>n;
        for(int i=1;i<=n;i++){
            string name1,name2;
            cin>>name1>>name2;
            int a=get_index(name1);
            int b=get_index(name2);
            graph[a].push_back(b);
            sign[b]=true;
        }
        cin>>m;
        for(int i=1;i<=m;i++){
            string name1,name2;
            cin>>name1>>name2;
            int a=get_index(name1);
            int b=get_index(name2);
            e[a].push_back(node(b,i));
            e[b].push_back(node(a,i));
        }
    }
    void targin(int u){
        color[u]=1;
        for(int i=0;i<e[u].size();i++){
            int ID=e[u][i].index;
            if(ans[ID])
                continue;
            int v=e[u][i].to;
            if(color[v]==0)
                    //0代表v未访问过
                continue;
            if(color[v]==1)
                    //1代表正在访问,所以u和v的最近公共祖先就是v
                ans[ID]=v;
            if(color[v]==2)
                    //2代表访问完毕的点,所以u和v的最近公共祖先就是v当前的祖先
                ans[ID]=find(v);
        }
        for(int i=0;i<graph[u].size();i++){
            int v=graph[u][i];
            targin(v);
                    //一个节点dfs完后,标记vv为访问完毕的点,并更新父节点
            color[v]=2;
            f[v]=u;
        }
    }
    void solve(){
        for(int i=1;i<=n;i++)
            if(!sign[i])
                root=i;
        targin(root);
        for(int i=1;i<=m;i++)
            cout<<str[ans[i]]<<endl;
    }
    int main(){
        init();
        input();
        solve();
        return 0;
    }        
  • 相关阅读:
    Protocol Buffers教程
    Paxos、ZAB、RAFT协议
    kafka自定义序列化器
    Java cas原理
    常见的排序算法
    Java反射
    etcd单机集群
    通过tomcat shutdown port关闭tomcat
    Java ConcurrentHashMap初始化
    LaTeX技巧892: Ubuntu 安装新版本TeXLive并更新
  • 原文地址:https://www.cnblogs.com/starve/p/10745906.html
Copyright © 2011-2022 走看看