zoukankan      html  css  js  c++  java
  • HDU

    pro:给定N+1个点的树,有M对关键点,现在让你破坏最少的点,使得M对关键点不连通。

    sol:贪心,我们把M对点按照LCA深度排序,每次破坏LCA。 如果一对点(u,v,lca),u-lca-v有点被破坏,则可以不用破坏新的点。 我们可以用dfs序+树状数组来处理。 如果破坏了一个点,则给它的子树都+1。  那么u-lca-v有点被破坏等价于,u或者v至少一个属于已经被破坏的点的子树,树状数组查询即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    int fa[maxn][15],Laxt[maxn],Next[maxn],To[maxn],dep[maxn];
    int sum[maxn],cnt,in[maxn],times,out[maxn],ans;
    struct fcy{ int u,v,lca; }s[maxn];
    bool cmp(fcy x,fcy y){ return dep[x.lca]>dep[y.lca];}
    void add(int x,int val){ while(x<=times){ sum[x]+=val; x+=(-x)&x;}}
    int query(int x){int res=0; while(x){ res+=sum[x];x-=(-x)&x;}return res;}
    void adde(int u,int v){ Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;}
    void dfs(int u,int f)
    {
        in[u]=++times;
        dep[u]=dep[f]+1; fa[u][0]=f;
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]!=f) dfs(To[i],u);
        }
        out[u]=times;
    }
    int LCA(int u,int v)
    {
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=14;i>=0;i--)
            if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
        if(u==v) return u;
        for(int i=14;i>=0;i--)
            if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
        return fa[u][0];
    }
    int main()
    {
        int N,Q,u,v;
        while(~ scanf("%d",&N)){
            N++; ans=0;
            rep(i,1,N) Laxt[i]=0; cnt=0;
            rep(i,1,N-1){
               scanf("%d%d",&u,&v);
               u++; v++;
               adde(u,v); adde(v,u);
            }
            rep(i,1,times) sum[i]=0; times=0;
            dfs(1,0);
            rep(i,1,14) rep(j,1,N)
              fa[j][i]=fa[fa[j][i-1]][i-1];
            scanf("%d",&Q);
            rep(i,1,Q){
               scanf("%d%d",&s[i].u,&s[i].v);
               s[i].u++; s[i].v++;
               s[i].lca=LCA(s[i].u,s[i].v);
            }
            sort(s+1,s+Q+1,cmp);
            rep(i,1,Q){
               int t=query(in[s[i].u])+query(in[s[i].v]);
               if(!t) {
                  ans++;
                  add(in[s[i].lca],1);
                  add(out[s[i].lca]+1,-1);
               }
             }
             printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    MySql性能调优三(explain/desc执行计划)
    MySql性能调优二(BTree、B+Tree与索引数据结构)
    MySql性能调优一(存储引擎InnoDB,MyISAM)
    PHP 数组底层实现原理
    哈希算法及其应用场景
    散列表、散列函数和散列冲突
    PHP中的XML解析的5种方法
    特殊的线性表:递归
    Navicat12破解教程(Navicat_Keygen_Patch_By_DFoX V5.6)
    svn服务端安装、迁移教程、Eclipse切换svn连接库
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10754831.html
Copyright © 2011-2022 走看看