超时代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int head[N],e[N],ne[N],idx;
int dp[N];
bool st[N];
int n;
void add(int x,int y){
e[idx]=y;
ne[idx]=head[x];
head[x]=idx;
idx++;
}
int dfs(int d){
int res=1;
for(int i=head[d];i!=-1;i=ne[i]){
if(!st[e[i]]){
st[e[i]]=true;
res=res+dfs(e[i]);
st[e[i]]=false;
}
}
return res;
}
int main(){
memset(head,-1,sizeof(head));
cin>>n;
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++){
st[i]=true;
for(int j=head[i];j!=-1;j=ne[j]){
st[e[j]]=true;
dp[i]=max(dp[i],dfs(e[j]));
st[e[j]]=false;
}
st[i]=false;
}
int res=1;
for(int i=2;i<=n;i++){
if(dp[i]<dp[res]){
res=i;
}
}
cout<<dp[res];
return 0;
}
超时代码每一次求删除某个点时剩余连通块的最大值,都会把这个点的所有儿子节点都遍历一遍求和然后选出最大值,
其实求删除每一个点后剩余连通块的最大值的操作都是相同的,这个for循坏可以用递归来实现,求过的点就不会再再次被访问到。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010,M=N*2;
int head[N],e[M],ne[M],idx;
bool st[N];
int n,ans=0x3f3f3f3f;
void add(int x,int y){
e[idx]=y;
ne[idx]=head[x];
head[x]=idx;
idx++;
}
int dfs(int d){
st[d]=true;
int sum=1,res=0;
for(int i=head[d];i!=-1;i=ne[i]){
if(st[e[i]]){
continue;
}
int d=dfs(e[i]);
sum=sum+d;
res=max(res,d);
}
res=max(n-sum,res);
ans=min(res,ans);
return sum;
}
int main(){
memset(head,-1,sizeof(head));
cin>>n;
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1);
cout<<ans;
return 0;
}