您的位置:首页 > 其它

hdu4714 树形dp

2016-09-19 21:22 337 查看


Tree2cycle

Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)

Total Submission(s): 2218    Accepted Submission(s): 526


Problem Description

A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 unit of cost respectively. The nodes are labeled from 1 to N. Your job is to transform the tree to a cycle(without superfluous edges) using minimal cost.

A cycle of n nodes is defined as follows: (1)a graph with n nodes and n edges (2)the degree of every node is 2 (3) each node can reach every other node with these N edges.

 

Input

The first line contains the number of test cases T( T<=10 ). Following lines are the scenarios of each test case.

In the first line of each test case, there is a single integer N( 3<=N<=1000000 ) - the number of nodes in the tree. The following N-1 lines describe the N-1 edges of the tree. Each line has a pair of integer U, V ( 1<=U,V<=N ), describing a bidirectional edge
(U, V).

 

Output

For each test case, please output one integer representing minimal cost to transform the tree to a cycle.

 

Sample Input

1
4
1 2
2 3
2 4

 

Sample Output

3
Hint
In the sample above, you can disconnect (2,4) and then connect (1, 4) and
(3, 4), and the total cost is 3.

 

Source

2013 ACM/ICPC Asia Regional Online —— Warmup

题意:给定一棵树,问最少要删除 添加 几次边可以使该树变成一个环;

每次都将儿子节点变成一条链。



给个样例。 黑线表示操作数。  黑线与红线相交表示删除该红线。  两节点的黑线表示, 添加一条边。  

得到如图:



也就是说,

如果该节点有二个以上(包括二个)的分叉, 那么就首先与父亲断离,形成一条游离链。 还需要断离 sum – 2个儿子, 并且再次连接  sum – 2个儿子构成一条直链。

这里已经花费了  2 * (sum – 2) + 1次操作。 还需要一次操作是与下一个游离链相连。 即 2 * (sum – 1) 次操作。

如果该节点就是自定义的根节点, 那么其无需与父亲断离, 也无需与下一个游离链相连。 即需要 2 * (sum – 2)次操作。

每次与父亲断离后。 父亲就失去一个儿子节点。

如果该节点只有一个分叉或者是叶子节点, 什么都不管, 返回true. 表示 还是原树一起。

然后再 + 1就会构成一个环。

计算sum值呢,要进行深搜,从底层向上进行计算,当该节点与父亲节点断开连接后,那么父亲节点分叉要减1,所以计算当前分叉个数时要减去儿子中分叉个数大于等于2的,

AC代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn=2000100;

int in[maxn],vis[maxn];
struct Edge
{
int v,next;
} edge[maxn*2];
int tot,head[maxn];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int ans;
int son[maxn];
int dfs(int u,int pre)
{
int v,sum=0;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].v;
if(v==pre)
continue;
sum+=dfs(v,u);
}
son[u]=sum;
if(sum>=2)
{
if(u==1)
ans+=(sum-2)*2;
else
ans+=(sum-1)*2;
return 0;
}
return 1;

}
int main()
{
int t,n,u,v;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();

for(int i=1; i<n; i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
ans=0;
dfs(1,1);
for(int i=1;i<=n;i++)
{
cout<<son[i]<<" ";
}
cout<<endl;
printf("%d\n",ans+1);
}
return 0;
}
/**
8
1 2
1 3
1 4
2 5
2 6
4 7
4 8

10
1 2
2 3
2 4
2 5
3 6
3 7
7 8
7 9
7 10

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: