【FZU 2185】 Problem 2185 树的路径覆盖(建树)
Problem 2185 树的路径覆盖
Accept: 100 Submit: 275
Time Limit: 2000 mSec Memory Limit : 32768 KB
Problem Description
給一棵树, 用最少的路径去覆盖所有的边, 求(1)允许边被重复覆盖, (2)不允许边被重复覆盖.
Input
第一行是组数T(T <= 20). 每组两行, 第一行是n(1 <= n <= 10^5), 第二行是n - 1个数(0-based), 第i个数x[i]表示有一条边(x[i], i + 1), (0 <= i <= n - 2).
Output
两个值,第一个值是允许边被重复覆盖情况下的答案,第二个值是不允许边被重复覆盖下的答案,用一个空格分隔.
Sample Input
2170 0 1 1 2 2
Sample Output
0 02 3
Source
FOJ有奖月赛-2015年03月给出一颗0为根的树(不一定为二叉树) 结点编号0~n-1 问可重复最少覆盖路径数和不可重复最少覆盖路径数
可重复好想 两个两个叶子结点间连路 为(leaf+1)/2叶子结点的一半(向上取整)
不可重复的 先把枝叶去掉 只留下一整棵树 答案同为叶子结点一半
当某个节点有分支时 其实是问以该节点为根的新树上不可重复最少覆盖路径数 同上处理
去分支 后的叶子结点 其实就是根的出度
这样统计各结点的出度的一半 由于从非0结点发出的边有一条包含于0(总父亲)内 因此需要向下取整 统计之后即为答案
代码如下:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int out[100010];
int main()
{
int t,n,u,leaf,ans;
scanf("%d",&t);
while(t--)
{
memset(out,0,sizeof(out));
scanf("%d",&n);
for(int i = 1; i < n; ++i)
{
scanf("%d",&u);
out[u]++;
}
leaf = 0;
ans = (out[0]+1)>>1;
for(int i = 1; i < n; ++i)
{
if(!out[i]) leaf++;
ans += out[i]>>1;
}
printf("%d %d\n",(leaf+1)>>1,ans);
}
return 0;
}