码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4868 树分治

时间:2015-07-05 12:16:12      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<iostream>
#include<queue>
using namespace std;

const int M = 60005;
struct Edge{
    int v, next, w;
}edge[M << 2], ee[M ];
map<int, int> mp;
int E, head[M], hh[M], EE;
int root, mmax;
int cc[M], dd[M];
int cnt[M], mx[M], sz[M];
int wh[M], dep[M], dis[M];
int n, m, k;
int vis[M];

void init(){
    memset(head, -1, sizeof(head));
    memset(hh, -1, sizeof(hh));
    memset(cnt, 0, sizeof(cnt));
    E = EE = 0;
}

void add_edge(int s, int v, int w){
    edge[E].v = v;
    edge[E].w = w;
    edge[E].next = head[s];
    head[s] = E ++;
}

void add(int s, int v, int w){
    ee[EE].v = v;
    ee[EE].next = hh[s];
    ee[EE].w = w;
    hh[s] = EE ++;
}

const int inf = 0x3f3f3f3f;
int mm ;

void Dijk(){
    priority_queue<pair<int, int> > q;
    for(int i = 0; i < n; i ++){dis[i] = inf;}
    dis[0] = 0;
    memset(vis, 0, sizeof(vis));
    q.push(make_pair(0, 0));
    while(!q.empty()){
        pair<int, int> now = q.top(); q.pop();
        int u = -now.second; int dd = -now.first;
        if(vis[u] == 1) continue;
        vis[u] = 1;
        for(int i = head[u]; i != -1; i = edge[i].next){
            int v = edge[i].v;
            if(dis[v] > dis[u] + edge[i].w){
                dis[v] = dis[u] + edge[i].w;
                wh[v] = u;
                q.push(make_pair(-dis[v], -v));
            }
        }
    }
    for(int i = 1; i < n; i ++) {
        add(wh[i], i, - dis[wh[i]] + dis[i]);
        add(i, wh[i], - dis[wh[i]] + dis[i]);
    }
}

void dfs1(int u, int fa){
    sz[u] = 1; mx[u] = 0;
    for(int i = hh[u]; i != -1; i = ee[i].next){
        int v = ee[i].v;
        if(v != fa && vis[v] == 0){
            dfs1(v, u);
            mx[u] = max(mx[u], sz[v]);
            sz[u] += sz[v];
        }
    }
}

void dfs2(int u, int fa, int rt){
    mx[u] = max(mx[u], sz[rt] - sz[u]); if(mx[u] < mmax){
        mmax = mx[u]; root = u;
    }
    for(int i = hh[u]; i != -1; i = ee[i].next){
        int v = ee[i].v;
        if(v != fa && vis[v] == 0){
            dfs2(v, u, rt);
        }
    }
}

void dfs(int u, int fa, int step, int stop, int w){
    if(w > cc[step]) {
        cc[step] = w;
        dd[step] = 1;
    }else if(w == cc[step]) dd[step] ++;
    if(step == stop) return ;
    for(int i = hh[u]; i != -1; i = ee[i].next){
        int v = ee[i].v;
        if(v == fa || vis[v]) continue;
        dfs(v, u, step+1, stop, w + ee[i].w);
    }
}

int cal(int u, int tn, int w){
    //printf("%d %d %d\n", u, sum, w);
    for(int i = 0; i <= tn+1; i ++) {cc[i] = 0; dd[i] = 0;}
    //memset(cnt, 0, sizeof(cnt));
    dfs(u, -1, 1, tn, w);
    int ans = 0;
    if(cc[k-1]) {
        mm = max(mm, cc[k-1]);
        mp[cc[k-1]] += dd[k-1];
    }
    //printf("u = %d\n", u);
    //for(int i = 1; i <= tn+1; i ++) printf("%d %d %d, %d\n", cc[i], dd[i], cnt[i], dep[i]);
    for(int i = 1; i < k; i ++){
        if(  cc[i] == 0) break;
        mp[cc[i] + cnt[k - 1 - i]] += dd[i] * dep[k-1-i];
        mm = max(mm, cc[i] + cnt[k-1-i]);
    }
    return ans;
}

void update(int tn){
    for(int i = 1; i <= tn; i ++){
        if(cc[i]) {
            if(cnt[i] == cc[i]) dep[i] += dd[i];
            else if(cnt[i] < cc[i]) {
                cnt[i] = cc[i]; dep[i] = dd[i];
            }
        }
        else break;
    }
}


int ans;
void solve(int u){
    mmax = M;
    root = u;
    dfs1(u, -1);
    dfs2(u, -1, u);
    vis[root] = 1;
    for(int i = 0; i <= mx[root]+1; i ++) {cnt[i] = 0; dep[i] = 0;}
    for(int i = hh[root]; i != -1; i = ee[i].next){
        int v = ee[i].v;
        if(vis[v]) continue;
        int tmp = cal(v, min(k-1, mx[v] + 1), ee[i].w);
        update(min(k-1, mx[v] + 1));
    }
    for(int i = hh[root]; i != -1; i = ee[i].next){
        int v = ee[i].v;
        if(vis[v] == 0)
        solve(v);
    }
}

/*
int pah(int u, int fa, int step){
    int m1, m2;
    m1 = 0; m2 = 0;
    for(int i = hh[u]; i != -1; i = ee[i].next){
        int v = ee[i].v;
        if(v == fa) continue;
        int tmp = pah(v, u, step+1) + ee[i].w;
        if(tmp > m1){
            m2 = m1; m1 = tmp; 
        }else if(tmp > m2) m2 = tmp;
    }
    int ret = m1;
    if(step > m1){
        m2 = m1; m1 = step;
    }else if(step > m2) m2 = step;
    mm = max(mm, m1+m2+1);
    return ret;
}
*/
int read(){
    int ans = 0;
    char g;
    while((g = getchar()) == ‘ ‘ || g == ‘\n‘) ;
    ans = g - ‘0‘;
    while((g = getchar()) != ‘ ‘ && g != ‘\n‘) ans = ans * 10 + g - ‘0‘;
    return ans;
}
int main(){
    int T;
    //freopen("1011.in", "r", stdin);
    scanf("%d", &T);
    //T = read();
    while(T --){
  //      n = read(); m = read(); k = read();
        scanf("%d%d%d", &n, &m, &k);
        int a, b, c;
        init();
        for(int i = 0; i < m; i ++){
//            a = read(); b = read(); c = read();
            scanf("%d%d%d", &a, &b, &c);
           a --; b --;
            add_edge(a, b, c);
            add_edge(b, a, c);
        }
        Dijk();
        memset(vis, 0, sizeof(vis));
        mm = 0;
        solve(1);
        printf("%d %d\n", mm, mp[mm]);
    }
    return 0;
}

  

hdu 4868 树分治

标签:

原文地址:http://www.cnblogs.com/acmood/p/4621852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!