作为一个咸鱼中的咸鱼中的蒟蒻中的蒟蒻的OIer选手,今天看到小初一过来心里甚是高兴,终于有人比我弱了,于是我决定水一道题吓吓他们,结果……
点击传送:http://poj.org/problem?id=3107
又是全是英文心塞呀。
“没关系,题目的翻译版加简化版就是给定一棵树,求树的所有重心,按照编号从小到大的顺序输出。”zyy突然来到我的身边拍了我的肩膀说。
滚一边去!没错题目的意思就是zyy说的那样。在我们学校OJ就有这个解释,谁都知道。但做法呢?
学校OJ里介绍了这种做法:
分析:本题与上题基本上一样,只是求的量不同,既然我们在找树的重心的时候用的树型dp,而且是求的子树中节点数的最大值,然后求所有最
大值的最小值,那么就有可能存在多个重心,我们每更新到一个最小值的时候就记录其它的最小值也为这个最小值的重心,这样下去就会找到所
有的重心.
作为一个咸鱼OIer,看到后脑里就是懵。并竟我的信仰是:暴力出奇迹,骗分过样例!于是我灵机一动(好像有点怪怪的)产生了一种想法。不如我们开个数组记录每个点删去后最大子树的节点数。dfs完后扫一遍这个数组,如果等于最小值就输出,重要部分的代码长这样:
void dfs(int num)
{
used[num] = 1;
d[num] = 0;
int max1 = 0;
for(int i=p[num];~i;i=a[i].next)
if(!used[a[i].to])
{
int u = a[i].to;
dfs(u);
d[num] += d[u] ;
max1 = max(max1,d[u]);
}
d[num]=d[num]+1;
max1 = max(max1,n-d[num]);
max2[num]=max1;//记录最大子树
if(max1 < size || max1 == size && num < ans)
size = max1;
}
int main()
{
init();
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1);
int k=0;
//扫一遍
for(int i=1;i<=n-1;i++)
if(max2[i]==size)b[++k]=i;
for(int i=1;i<=k-1;i++)printf("%d ",b[i]);
printf("%d\n",b[k]);
return 0;
}
做完了。
zyy:呵呵呵,我早做完了!
然而这只是小数据的做法。
大数据的以后补。