Sicily 1140 國王的遺產

貪心,主要卡在劃分樹的子樹上。
#include <iostream>
using namespace std;
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <deque>
#include <memory.h>

vector<int> tree[30002];
int node_ctr[30002];
int n,k;
vector<int> result;
int set_node_ctr(int root) {
    if (node_ctr[root]!=0)
        return node_ctr[root];
    int s=tree[root].size();
    int i,tmp;
    for (i=0;i<tree[root].size();i++) {
        if (tree[root][i]==0)
            s--;
    }
    if (s==0) {
        node_ctr[root] = 1;
        return node_ctr[root];
    }
    
    tmp = 1;
    for (i=0;i<tree[root].size();i++) {
        if (tree[root][i]!=0)
            tmp+=set_node_ctr(tree[root][i]);
    }

    node_ctr[root] = tmp;
    return tmp;
}
int get_minID(int root) {
    deque<int> q;
    int minid = root;
    q.push_back(root);
    int tmp;
    while (!q.empty()) {
        tmp=q.front();
        q.pop_front();
        if (tmp<minid)
            minid=tmp;
        for(int i=0;i<tree[tmp].size();i++) {
            if (tree[tmp][i]!=0)
                q.push_back(tree[tmp][i]);
        }
    }
    return minid;
}
void delete_node(int root) {
    int flag=0;
    for (int i=1;i<=n;i++) {
        for (int j=0;j<tree[i].size();j++) {
            if (tree[i][j]==root) {
                tree[i][j]=0;
                flag=1;
                break;
            }
        }
        if (flag==1)
            break;
    }
}
int get_next_root(int total, int root_id) {
    int t1,t2,r1,r2;
    int tmp = total/2;
    int i;
    int num;
    deque<int> q;
    
    t1=t2=-1;
    r1=r2=-1;
    q.push_back(root_id);
    while (!q.empty()) {
        int top_id = q.front();
        q.pop_front();
        for (i=0;i<tree[top_id].size();i++) {
            num = tree[top_id][i];
            if (num==0)
                continue;
            q.push_back(num);
            if (node_ctr[num]!=0&&node_ctr[num]<=tmp) {
                if (node_ctr[num]>t1) {
                    t1=node_ctr[num];
                    r1=num;
                }
            }
            else if (node_ctr[num]==t1) {
                if (get_minID(num)<r1)
                    r1=num;
            }
            if (node_ctr[num]!=0&&total-node_ctr[num]<=tmp) {
                if (total-node_ctr[num]>t2) {
                    t2 = total-node_ctr[num];
                    r2 = num;
                }
                else if (total-node_ctr[num]==t2) {
                    if (get_minID(num)>r2)
                        r2=num;
                }
            }
        }
    }
    if (t1<t2) 
        return r2;
    else if (t1==t2 && get_minID(r1) == get_minID(root_id)) {
        delete_node(r2);
    }
    else {
        delete_node(r1);
    }           
    return -1;
}
void make_tree(int root) {
    int i,j;
    for (i=0;i<tree[root].size();i++) {
        int tmp = tree[root][i];
        for (j=0;j<tree[tmp].size();j++) {
            if (tree[tmp][j]==root)
                tree[tmp][j]=0;
        }
        make_tree(tmp);
    }
} 
void solve() {
    memset(node_ctr, 0, sizeof(node_ctr));
    set_node_ctr(1);
    int i, root;
    root = 1;
    int total = n;
    for (i=0;i<k-1;i++) {
        int tmp = get_next_root(total, root);
        if (tmp > 0)
            root = tmp;
        memset(node_ctr, 0, sizeof(node_ctr));
        set_node_ctr(root);
        result.push_back(total - node_ctr[root]);
        total = node_ctr[root];
    }
    int sum = 0;
    for (i=0;i<result.size();i++)
        sum+=result[i];
    result.push_back(n-sum);
}
int main() {
    int i;
    int x,y;

    while(scanf("%d",&n)!=EOF) {
        scanf("%d",&k);
        result.clear();
        for (i=0;i<=n;i++) {
            tree[i].clear();
        }
        for (i=0;i<n-1;i++) {
            scanf("%d%d",&x, &y);
            tree[x].push_back(y);
            tree[y].push_back(x);
        }
        make_tree(1);
        solve();
        for (i=0;i<result.size()-1;i++)
            cout << result[i] << " ";
        cout << result[i] << endl;
    }
    return 0;
}                               

發佈了144 篇原創文章 · 獲贊 7 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章