SGU195 New Year Bonus Grant(树形DP|贪心)

这题解了好久,其实实现倒没什么难的,就是刚开始用vector存父子间关系导致超时,找不到原因各种抓狂(写的乱七八糟的代码华丽丽地赢了叉姐五毛钱)。

树形DP解法:

如果一个点被标记,那么他的所有子节点都是不可被标记的。

若一个节点没有被标记,那么就从其子节点中选择标记一个,其他的不标记。

//SGU 195 New Year Bonus Grant
//树形DP
//by night_watcher

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

#define N 500001


int n,tot,cnt;
int dp[N][2];
int head[N];
int to[N];
int path[N];

struct NODE{
    int v;
    int next;
}node[N];


void add(int i,int parent){
    node[tot].v=i;
    node[tot].next=head[parent];
    head[parent]=tot++;
    return ;
}
void dfs(int k){
    int i,j;
    dp[k][0]=0;
    dp[k][1]=1;
    int sum=0,dis=0;
    for(i=head[k];i!=-1;i=node[i].next){
        dfs(node[i].v);
        sum+=dp[node[i].v][0];
        if(dis<dp[node[i].v][1]-dp[node[i].v][0]){
            dis=dp[node[i].v][1]-dp[node[i].v][0];
            to[k]=node[i].v;
        }
    }
    dp[k][1]+=sum;
    dp[k][0]+=sum+dis;
    return ;
}

void find_path(int k,int b){
    if(b){
        path[cnt++]=k;
        for(int i=head[k];i!=-1;i=node[i].next){
            find_path(node[i].v,0);
        }
    }
    else{
        for(int i=head[k];i!=-1;i=node[i].next){
            if(node[i].v==to[k]){
                find_path(node[i].v,1);
            }
            else find_path(node[i].v,0);
        }
    }
    return ;
}

int main(){
        int i,j;
        while(cin>>n){
            memset(head,-1,sizeof(head));
            tot=0;
            cnt=0;
            for(i=2;i<=n;i++){
                cin>>j;
                add(i,j);
            }
            dfs(1);
            cout<<dp[1][0]*1000<<endl;
            find_path(1,0);
            sort(path,path+cnt);

            cout<<path[0];
            for(i=1;i<cnt;i++){
                cout<<" "<<path[i];
            }
            cout<<endl;
        }
    return 0;
}


贪心解法:

优先选择层数最大,其自身及父节点都没有被标记的节点标记,选择该节点,标记该节点和其父节点。

//SGU195 New Year Bonus Grant
//贪心算法
//by night_watcher

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;

#define N 500001

struct node{
    int depth;
    int i;
}order[N];

int parent[N];

int n;
bool mark[N];
vector<int> result;

bool cmp(const node a,const node b){
    return a.depth>b.depth;
}

int main(){
    int i,j;
    order[1].depth=0;
    order[1].i=1;
    while(cin>>n){
        for(i=2;i<=n;i++){
            cin>>parent[i];
            order[i].depth=order[parent[i]].depth+1;
            order[i].i=i;
        }
        sort(order+2,order+n+1,cmp);
        result.clear();
        memset(mark,0,sizeof(mark));
        for(i=2;i<=n;i++){
            if(!mark[order[i].i]&&!mark[parent[order[i].i]]){
                result.push_back(order[i].i);
                mark[order[i].i]=1;
                mark[parent[order[i].i]]=1;
            }
        }
        cout<<result.size()*1000<<endl;
        sort(result.begin(),result.end());
        cout<<result[0];
        for(i=1;i<result.size();i++){
            cout<<" "<<result[i];
        }
        cout<<endl;
    }
    return 0;
}


 

你可能感兴趣的:(贪心,树形DP)