題意:給出一個樹形圖,要求把該樹形成一個環最少的步驟(斷開一條邊和形成一條邊都需一步)
分析:很明顯,要想把樹形成一個環,就要先把其分裂成m條子鏈之後把子鍊形成環需要的步驟是2*m+1,所以只需要m最小即可;貪心,以度爲1的節點爲根節點進行深搜,在回溯的時候對於邊(u,v)如果son[v]>=2,則需要斷開v兒子的son[v]-2條邊和<u,v>邊,然後刪除v節點,依次類推回溯上去最後的結果就是m的值;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"math.h"
#include"vector"
#include"stack"
#include"map"
#define eps 1e-4
#define inf 10000000
#define M 1001009
#define PI acos(-1.0)
using namespace std;
struct node
{
int u,v,next;
}edge[M*2];
int t,head[M],vis[M],son[M],degree[M],num,fa[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void dfs(int u,int f)
{
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].v;
if(v==f)continue;
fa[v]=u;
dfs(v,u);
if(son[v]>=2)
{
num+=degree[v]-2;//刪除v的n-1個兒子以及<u,v>
vis[v]=1;//刪除v節點
degree[fa[v]]--;//讓其父節點的度-1
}
if(!vis[v])
son[u]+=1;//統計兒子個數
}
}
int main()
{
int Case,n,i;
scanf("%d",&Case);
while(Case--)
{
scanf("%d",&n);
init();
memset(degree,0,sizeof(degree));
for(i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
degree[a]++;
degree[b]++;
}
num=0;
memset(fa,-1,sizeof(fa));
memset(son,0,sizeof(son));
memset(vis,0,sizeof(vis));
int root;
for(i=1;i<=n;i++)
if(degree[i]==1)
{
root=i;
break;
}
dfs(root,-1);
printf("%d\n",2*num+1);
}
}