zoukankan      html  css  js  c++  java
  • 树分治专题(学习笔记+做题记录)

    点分治

      点分治可以用来处理有关树上路径的问题

      首先选取当前子树的重心作为分治点,因为重心可保证最大的子树不超过(u/2),这样每次递归的处理下去,复杂度是(nlogn)的

      求重心代码:

    void getroot(int u,int par){
        sz[u]=1,son[u]=0;
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(vis[v] || v==par) continue;
            getroot(v,u);
            sz[u]+=sz[v];
            son[u]=max(son[u],sz[v]); 
        }
        son[u]=max(son[u],sum-sz[u]);
        if(son[u]<maxson){
            maxson=son[u];
            rt=u;
        }
    }
    View Code

      

    题目:

    IOI2011 Race

      题意:给定一棵树,每条边有边权,求一条路径,权值和等于k,且边的数量最小

      solution:

      记录s[i],当前点到分治中心的边数,d[i]当前点到分治中心的距离,f[i]已统计完的子树中,距分治中心距离为 i 的路径中的最小边数

      处理当前子树时,直接用f数组更新答案

      每次统计完一棵子树的答案之后,更新f数组

      这样既可以考虑到所有的路径,又避免重复统计答案

      

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1000010;
    const int INF = 1e9+7;
    
    int n,k,ans=INF;
    int sum,maxs;
    
    int h[maxn],size;
    struct E{
        int to,next,cost;
    }e[maxn<<1];
    void add(int u,int v,int w){
        e[++size].to=v;
        e[size].next=h[u];
        e[size].cost=w;
        h[u]=size;
    }
    
    int rt;
    int vis[maxn],sz[maxn],son[maxn];
    int d[maxn],s[maxn],f[maxn*10],c[maxn],ton[maxn*10],tot,cnt;
    
    void getroot(int u,int par){
        sz[u]=1,son[u]=0;
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(v==par||vis[v]) continue;
            getroot(v,u);
            sz[u]+=sz[v];
            son[u]=max(son[u],sz[v]);
        }
        son[u]=max(son[u],sum-sz[u]);
        if(son[u]<maxs){
            maxs=son[u];
            rt=u;
        }
    }
    
    void dfs(int u,int par,int chang){
        d[u]=d[par]+chang;
        if(d[u]<=k) ton[++tot]=d[u];
        s[u]=s[par]+1;
        c[++cnt]=u;
        if(k>=d[u]) ans=min(ans,f[k-d[u]]+s[u]);
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==par) continue;
            dfs(v,u,e[i].cost);
        }
    }
    
    void solve(int u){
        vis[u]=1;
        tot=0; f[0]=0; d[u]=0; s[u]=0;
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            cnt=0; 
            dfs(v,u,e[i].cost);
            
            for(int j=1;j<=cnt;++j){
                if(d[c[j]]>k) continue;
                f[d[c[j]]]=min(f[d[c[j]]],s[c[j]]);
            }
        }
        
        for(int i=1;i<=tot;++i) f[ton[i]]=INF;
        
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            sum=sz[v],maxs=INF,rt=0;
            getroot(v,0);
            solve(rt);
        }
    }
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}
    
    int main(){
        memset(h,-1,sizeof(h));
        n=read(),k=read();
        int u,v; ll w;
        for(int i=1;i<=1000000;++i) f[i]=INF;
        for(int i=1;i<n;++i){
            u=read(),v=read(),w=read();
            u++,v++;
            add(u,v,w),add(v,u,w);
        }
        
        sum=n; maxs=INF;
        getroot(1,0);
        
        solve(rt);
        
        printf("%d\n",ans==INF?-1:ans);
        
        return 0;
    }
    View Code

    Spoj 1825 Free tour II
      

  • 相关阅读:
    一个简单XQuery查询的例子
    《Microsoft Sql server 2008 Internals》读书笔记第七章Special Storage(1)
    《Microsoft Sql server 2008 Internals》读书笔记第八章The Query Optimizer(4)
    《Microsoft Sql server 2008 Internal》读书笔记第七章Special Storage(4)
    SQL Server中SMO备份数据库进度条不显示?
    《Microsoft Sql server 2008 Internal》读书笔记第七章Special Storage(5)
    《Microsoft Sql server 2008 Internal》读书笔记第七章Special Storage(3)
    《Microsoft Sql server 2008 Internal》读书笔记第八章The Query Optimizer(2)
    省市三级联动的DropDownList+Ajax的三种框架(aspnet/Jquery/ExtJs)示例
    FireFox意外崩溃时的手工恢复命令
  • 原文地址:https://www.cnblogs.com/tuchen/p/10482916.html
Copyright © 2011-2022 走看看