http://acdream.info/problem?pid=1015
关于图的博弈,a和b在一个生成树中选2个节点,距离较近的点则为各自拥有,如果离2人距离相等则属于a,a先选,求a能获得的最多点数。
思路就是a选了一个点,把这个点当成一个根节点来看,那么b只能在a的子树中来选,为了能获得更多,一定会选择a的子树中最多节点数的子树的根节点。那么为了使a得到最大,求每个点作为根节点时,其节点最多子树的最小值即可。
#include<bits/stdc++.h>
using namespace std;
struct node{
int a;
int nex;
int b;
};
int n;
node e[111111];
int ans[55555];
int fa[55555];
int js;
void add(int x, int y) {
js++;
e[js].a=y;
e[js].b=0;
e[js].nex=fa[x];
fa[x]=js;
}
void dfs(int x,int y)
{
for(int i=fa[x];i!=-1;i=e[i].nex)
{
if(e[i].a!=y)
{
dfs(e[i].a,x);
for(int j=fa[e[i].a];j!=-1;j=e[j].nex)
{
if(e[j].a==x)continue;
e[i].b+=e[j].b;
}
e[i].b+=1;
e[i^1].b=n-e[i].b;
}
}
}
int main(){
while(cin>>n)
{
js=-1;
memset(ans,0,sizeof(ans));
memset(fa,0xff,sizeof(fa));
int x,y;
for(int i=1;i<n;i++)
{
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,0);
int ans1=0x7ffffff;
for(int i=1;i<=n;i++){
for(int j=fa[i];j!=-1;j=e[j].nex){
ans[i]=max(ans[i],e[j].b);
}
ans1=min(ans1,ans[i]);
}
cout<<n-ans1<<endl;
}
return 0;
}