您的位置:首页 > 其它

[POJ 1741] DP + Tree 分治

2013-02-12 20:55 447 查看
题意:

给一棵树,有边权。问边权和<=k的路径有多少条。

解法:

TreeDp+分治。漆子超的论文。。

const int N = 1e4 + 9;
int n , k , ans;
struct EDGE{
    int to , len , next;
}edge[N << 1];
int head
 , tot;
void addedge(int u , int v , int len){
    edge[tot].to = v;
    edge[tot].len = len;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int sons
 , core , corecnt;
int dis
;
int lis
 , listot;
bool vis
;
void coredfs(int u , int v){    // Count the Sons
    sons[u] = 1;
    int ret = 1;
    for(int i = head[u] ; i != -1 ; i = edge[i].next){
        int go = edge[i].to;
        if (go == v || vis[go]) continue;
        coredfs(go , u);
        sons[u] += sons[go];
    }
}
void coreedit(int u , int v , int cnt){ //Find core
    int ret = 1;
    for(int i = head[u] ; i != -1 ; i = edge[i].next){
        int go = edge[i].to;
        if (go == v || vis[go]) continue;
        coreedit(go , u , cnt);
        checkMax(ret , sons[go]);
    }
    checkMax(ret , cnt - sons[u]);

    if (ret < corecnt){
        core = u;
        corecnt = ret;
    }
}
int Qcore(int u){       // Subtree's Core
    corecnt = INF;
    coredfs(u , 0);
    coreedit(u , 0 , sons[u]);
    return core;
}
void rushDis(int u , int len , int v){
    lis[listot++] = len;
    for (int i = head[u] ; i != -1 ; i = edge[i].next){
        int g = edge[i].to;
        if (g != v && !vis[g]) rushDis(g , len + edge[i].len , u);
    }
}
int calc(int u , int len){
    int ret = 0;
    listot = 0;
    rushDis(u , len , 0);
    sort(lis , lis + listot);
    int head = 0 , tail = listot - 1;
    while(head < tail){
        while(head < tail && lis[head] + lis[tail] > k) tail--;
        ret += tail - head;
        head++;
    }
    return ret;
}
void dfs(int u){    //Treedp   the subtree of Root-u
    Qcore(u);
    ans += calc(core , 0);
    vis[core] = 1;
    for (int i = head[core] ; i != -1 ; i = edge[i].next){
        int g = edge[i].to;
        if (!vis[g]){
            ans -= calc(g , edge[i].len);
            dfs(g);
        }
    }
}
void solve(){
    tot = 0;
    FLC(head , -1);
    REP(i , n - 1){
        int u , v , w;
        RD(u , v , w);
        addedge(u , v , w);
        addedge(v , u , w);
    }
    ans = 0;
    RST(vis);
    dfs(1);
    OT(ans);
}
int main(){
//    freopen("0.txt" , "r" , stdin);
//    freopen("1.txt" , "w" , stdout);
    while(RD(n , k) , n && k) solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: