题意: 最小要多少警察能把一棵树中所有小偷抓出来。 思路: 派一个警察守住路口,别的警察把这颗子树除了最大的一棵以外的都搜一遍,再一起往最大的那一颗子树过去,这时候就不需要派人守住路口了。 代码: #include<iostream> #include<vector> #include<iterator> using namespace std; #define MAXN 1005 vector<int> map[MAXN]; vector<int>::iterator it; int deg[MAXN]; bool visited[MAXN]; int ans; int max(int x,int y) { if (x>y) return x; else return y; } bool is_line(int n) { bool flag; int i; flag=true; for(i=1;i<=n;i++) if (map[i].size()>=3) flag=false; return flag; } void delete_leaf(int n) { int i,x; for(i=1;i<=n;i++) deg[i]=map[i].size(); for(i=1;i<=n;i++) if ( (deg[i]==1)) { ans++; if (map[i].size()==1) { x=map[i][0]; map[i].erase(map[i].begin()); for(it=map[x].begin();it!=map[x].end();it++) if (*it==i) { map[x].erase(it); break; } } } } int treedp(int x) { int i,max1,max2,sum; max1=max2=0; visited[x]=true; for(i=0;i<map[x].size();i++) if (!visited[map[x][i]]) { sum=treedp(map[x][i]); if (sum>max1) {max2=max1;max1=sum;} else if (sum>max2) {max2=sum;} } return max(max1,max2+1); } int main() { int n,a,b,i,j; bool flag; // freopen("1001_out.out","w",stdout); while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) map[i].clear(); for(i=1;i<=n-1;i++) { scanf("%d %d",&a,&b); map[a].push_back(b); map[b].push_back(a); } flag=true; while(flag) { flag=false; for(i=1;i<=n;i++) if (map[i].size()==2) { ans++; a=map[i][0]; b=map[i][1]; map[i].erase(map[i].begin()); map[i].erase(map[i].begin()); for(j=0;j<map[a].size();j++) if (map[a][j]==i) map[a][j]=b; for(j=0;j<map[b].size();j++) if (map[b][j]==i) map[b][j]=a; flag=true; } } ans=0; for(i=1;i<=n;i++) if (map[i].size()>0) break; memset(visited,0,sizeof(visited)); ans=treedp(i); printf("%d/n",ans); } }