zoukankan      html  css  js  c++  java
  • EOJ-A 昔我往矣(倍增LCA+乱搞)

    题解:

    既然只有5个点,那就无限乱搞,我的做法是不断取出当前点集两两之间的LCA插入点集,直到所有两两之间的LCA都已经在点集中了。

    这一步的时间复杂度我感觉是一个调和级数,是可以被忽略的。

    然后对每个点保存它的最深父亲,然后对点集建一棵树,对这棵树算边权贡献即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+100;
    int n,q;
    struct node {
        int u,v,w,nxt;
    }edge[maxn<<1];
    int head[maxn],tot;
    void addedge (int u,int v,int w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
        
        edge[tot].u=v;
        edge[tot].v=u;
        edge[tot].w=w;
        edge[tot].nxt=head[v];
        head[v]=tot++;
    } 
    
    int father[30][maxn];
    int h[maxn],d[maxn];
    void dfs (int x) {
        for (int i=head[x];i!=-1;i=edge[i].nxt) {
            int v=edge[i].v;
            if (v==father[0][x]) continue;
            father[0][v]=x;
            h[v]=h[x]+1;
            d[v]=d[x]+edge[i].w;
            //printf("%d %d
    ",v,h[v]);
            dfs(v);
        }
    }
    int lca (int x,int y) {
        if (h[x]<h[y]) swap(x,y);
        for (int i=20;i>=0;i--)
            if (h[x]-h[y]>>i) x=father[i][x];
        if (x==y) return x;
        for (int i=20;i>=0;i--) 
            if (father[i][x]!=father[i][y]) {
                x=father[i][x];
                y=father[i][y];
            }
        return father[0][x];
    }
    int getDis (int x,int y) {
        return d[x]+d[y]-d[lca(x,y)]*2;
    }
    int getH (int x,int y) {
        return h[x]+h[y]-h[lca(x,y)]*2;
    }
    int x[maxn],ans,f[maxn];
    vector<int> g[maxn];
    void dfs1 (int x,int f) {
        for (int y:g[x]) {
            if (y==f) continue;
            ans+=getDis(x,y);
            dfs1(y,x);
        }
    }
    int main () {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) head[i]=-1;
        for (int i=1;i<n;i++) {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            u++,v++;
            addedge(u,v,w);
        }
        h[1]=1;
        dfs(1);
        for (int i=1;i<=20;i++) for (int j=1;j<=n;j++) father[i][j]=father[i-1][father[i-1][j]];
        scanf("%d",&q);
        while (q--) {
            for (int i=1;i<=5;i++) scanf("%d",x+i),x[i]++;
            int m=5;
            set<int> st;
            for (int i=1;i<=5;i++) {
                st.insert(x[i]);
            }
            while (1) {
                int f=1;
                for (int i=1;i<=m;i++) {
                    for (int j=i+1;j<=m;j++) {
                        int tt=lca(x[i],x[j]);
                        if (!st.count(tt)) {
                            st.insert(tt);
                            x[++m]=tt;
                            f=0;
                        }
                    }
                }
                if (f) break;
            }
            for (int i=1;i<=m;i++) f[x[i]]=0,g[x[i]].clear(); 
            for (int i=1;i<=m;i++) {
                for (int j=i+1;j<=m;j++) {
                    int tt=lca(x[i],x[j]);
                    if (tt==x[i]) {
                        if (h[x[i]]>h[f[x[j]]]) {
                            f[x[j]]=x[i];
                        }
                    }
                    else if (tt==x[j]) {
                        if (h[x[j]]>h[f[x[i]]]) {
                            f[x[i]]=x[j];
                        }
                    }
                }
            }
            int rt=0;
            for (int i=1;i<=m;i++) {
                //printf("%d %d
    ",x[i],f[x[i]]);
                if (!f[x[i]]) {
                    rt=x[i];
                    continue;
                }
                g[f[x[i]]].push_back(x[i]);
            }
            ans=0;
            dfs1(rt,0);
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    According to TLD or attribute directive in tag file, attribute end does not accept any expressions
    Several ports (8080, 8009) required by Tomcat v6.0 Server at localhost are already in use.
    sql注入漏洞
    Servlet—简单的管理系统
    ServletContext与网站计数器
    VS2010+ICE3.5运行官方demo报错----std::bad_alloc
    java 使用相对路径读取文件
    shell编程 if 注意事项
    Ubuntu12.04下eclipse提示框黑色背景色的修改方法
    解决Ubuntu环境变量错误导致无法正常登录
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14382413.html
Copyright © 2011-2022 走看看