原题链接:
题目大意:给一棵树节点数最多为1000000 ,把这棵树通过删边 和加边使这棵树变成一个环,其中删边和加边的的代价都为 1,输出最小代价。
题目分析:由于最终要形成一个环其拥有的的边一定为n,故可以只讨论要删除多少条边, 由于要形成环,删边后每个节点最多只能有两个节点,
如果 当前节点有多于2个子节点与其相连,其与父亲节点连接的边要删除。
喳喳代码:
#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define N 1100000
using namespace std;
vector<int> tree[N];
int n;
int num;
int dfs(int pos,int p)//如果当前节点与父亲节点的连线要删去返回1否则返回0
{
int len=tree[pos].size();
if(len==1&&tree[pos][0]==p)
return 1;
int k=0;//记录当前节点的所有子节点返回的没有删除的与子节点连边的个数
int t;
for(int i=0; i<len; i++)
{
t=tree[pos][i];
if(t==p)continue;
k+=dfs(t,pos);
}
if(k>=2)//如果k>=2表示应该删除与父节点相连的边
{
num+=k-2;
if(pos!=1)
num++;
return 0;
}
return 1;
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
tree[i].clear();
int a,b;
for(int i=0; i<n-1; i++)
{
scanf("%d%d",&a,&b);
tree[a].push_back(b);
tree[b].push_back(a);
}
num=0;//表示要删除的边数
dfs(1,-1);
int ans=2*num+1;
printf("%d\n",ans);
}
return 0;
}