题目:poj 3107Godfather
题意:给定一棵无根树,删除树中一个节点,使得剩下各子树的包含的节点数最大值最小,问树中有多少个这样的节点? 然后字典序输出。
解题:遍历一遍所有节点就可以了。很简单,但是TLE了一上午,原因就是数据很变态吧,卡STL(可能是自己用的不熟练吧),然后自己写一个就直接AC了。
代码如下:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; #define N 50001 #define Max (1<<(31)-1) struct Node{ int v,next; }arcnode[N*2]; int vnode[N],v_dp[N],ans[N]; int ans_num,ans_key,k,num; bool vist[N]; void Addedge(int u,int v) { arcnode[k].v=v; arcnode[k].next=vnode[u]; vnode[u]=k++; } void dfs(int key) { vist[key]=false; v_dp[key]=1; int i,v,maxx=-1; for(i=vnode[key];i;i=arcnode[i].next) { v=arcnode[i].v; if(!vist[v]) continue; dfs(v); v_dp[key]+=v_dp[v]; maxx=max(maxx,v_dp[v]); } maxx=max(maxx,num-v_dp[key]); if(maxx==ans_key) ans[ans_num++]=key; if(maxx<ans_key) { ans_num=0; ans[ans_num++]=key; ans_key=maxx; } } int main() { while(~scanf("%d",&num)) { int i,a,b; k=1;ans_num=0;ans_key=num; memset(vist,true,sizeof(vist)); memset(vnode,0,sizeof(vnode)); for(i=1;i<num;i++) { scanf("%d%d",&a,&b); Addedge(a,b); Addedge(b,a); } dfs(1); sort(ans,ans+ans_num); for(i=0;i<ans_num;i++) { printf("%d",ans[i]); if(i!=ans_num-1) putchar(' '); else puts(""); } } }