HDU 4714 Tree2cycle:贪心

时间:2023-03-09 13:30:04
HDU 4714 Tree2cycle:贪心

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714

题意:

  给你一棵树,添加和删除一条边的代价都是1。问你将这棵树变成一个环的最小代价。

题解:

  贪心。

  将树变成环的过程,无非就是先拆掉k条边,将这棵树变成若干个链,然后再添加k+1条边,将所有链连成环。

  所以要让最终代价最小,就是让拆的边最少。

  对于节点i的子树,如果要将这棵子树全部变成链,则总共有两种情况:

    (1)节点i的儿子数 <= 1,这样的话根本就不用拆啊。

    (2)节点i的儿子数 >= 2:

      I.  节点i的所有儿子只保留2个,其他的一律删除。

      II. 将i与par[i]的边也删掉。这样的话可以减少par[i]的儿子数,使在节点par[i]时删的边尽可能少,显然更优。

  最后答案为:拆掉的边 * 2 + 1

AC Code:

 #pragma comment(linker,"/STACK:102400000,102400000")
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define MAX_N 1000005
#define MAX_E 2000005 using namespace std; struct Edge
{
int dst;
int nex;
}; int n,t;
int ans;
int cnt;
int head[MAX_N];
Edge edge[MAX_E]; void add(int s,int t)
{
edge[cnt].dst=t;
edge[cnt].nex=head[s];
head[s]=cnt++;
} void read()
{
scanf("%d",&n);
memset(head,-,sizeof(head));
cnt=;
int a,b;
for(int i=;i<n;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
} int dfs(int now,int p)
{
int cnt=;
for(int i=head[now];i!=-;i=edge[i].nex)
{
int temp=edge[i].dst;
if(temp!=p) cnt+=dfs(temp,now);
}
if(cnt>=)
{
ans+=cnt-+(p!=-);
return ;
}
return ;
} void work()
{
ans=;
dfs(,-);
printf("%d\n",ans*+);
} int main()
{
scanf("%d",&t);
while(t--)
{
read();
work();
}
}