树形dp-hdu-4714-Tree2cycle

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=4714

题目意思:

给一棵树,去掉一条边和增加一条边的花费都为1,求最小的花费,使该树变成一个环。

解题思路:

把任意一节点作为树根,dfs.

对于任何分叉超过1的节点,断开与父亲节点的连接,此时父亲节点就少了一个分叉。然后选两个分支作为两端,其它分支断开再连接共花费2,所有都做完后连到根上面.

先把所有的都连到根上面凑成直线,然后连成环。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x3fffffff
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; #define Maxn 1010000
struct Edge
{
int v;
struct Edge *next;
}*head[Maxn<<1],edge[Maxn<<1]; int n,cnt,ans; void add(int a,int b)
{
edge[++cnt].v=b,edge[cnt].next=head[a];
head[a]=&edge[cnt];
}
int dfs(int cur,int pa) //返回分支个数
{
int res=0;
struct Edge * p=head[cur]; while(p)
{
if(p->v!=pa)
res+=dfs(p->v,cur);
p=p->next;
}
if(res>=2) //超过两个分支,将其它分支连过来
{
if(cur==1) //树根
ans+=res-2; //不用练到其它地方
else
ans+=res-1; //选两个,其它的边都要断开和重新连接一次
return 0; //断开了
}
else
return 1; //作为一个单支
}
int main()
{
int t; scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
cnt=0;
memset(head,NULL,sizeof(head));
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
ans=0;
dfs(1,0);
printf("%d\n",ans*2+1);
}
return 0;
}
上一篇:PHP 导出Excel 文档


下一篇:HDU 4454 Stealing a Cake(枚举角度)