这题解了好久,其实实现倒没什么难的,就是刚开始用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; }