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
Sample Output//Accepted 2576 625ms GNU C++
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5+100;
int head[N];
struct Edge
{
int to;
int next;
}es[N<<1];
int son[N];
int n;
int ans1,ans2;
void dfs(int rt,int pa)
{
int cnt=0;
bool first=1;
for(int i=head[rt];~i;i=es[i].next)
{
int v=es[i].to;
if(v==pa) continue;
if(first)
first=0;
else
{
ans1++;
cnt++;
}
dfs(v,rt);
}
ans2+=cnt/2+cnt%2; //剔除同一节点的分枝数
}
void ini()
{
memset(head,-1,sizeof(head));
memset(son,0,sizeof(son));
ans1=ans2=0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ini();
for(int v=1;v<n;v++)
{
int u;
scanf("%d",&u);
es[v].to=v;
es[v].next=head[u];
head[u]=v;
es[v+n].to=u;
es[v+n].next=head[v];
head[v]=v+n;
son[u]++;
son[v]++;
}
for(int i=n-1;i>=0;i--)
if(son[i]==1)
{
dfs(i,-1);
ans1++;
ans2++;
break;
}
if(ans1)
printf("%d %d\n",(ans1-1)/2+(ans1-1)%2+1,ans2);
else
printf("0 0\n");
}
return 0;
}原文:http://blog.csdn.net/kalilili/article/details/44572891