Tree2cycle (树形dp)

题目大意:给你一颗生成树,求你将它改造为一个环,即每个节点的度为二,对于每一个节点来说,可以删除或增加边,每次操作的消耗均为1,求将它改造成环的最小消耗.

Input:

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.

in:

1
4
1 2
2 3
2 4

out:

3

思路:对于某一点的度n,如果它的度超过了2,为了给他归并到环中就需要n-2次断开操作与n-2次重连,如果是根节点的话总共只需要2*(n-1)次操作.归并过程递归实现

#include <iostream>
#include <cstring>
#define N 1000005
using namespace std;
int n,m,ans,cnt;
bool vis[N];
int head[N];
struct Node
{
    int to,next;

} e[N<<1];
void add(int x,int y)
{
    e[++cnt].to=y;
    e[cnt].next=head[x];
    head[x]=cnt;
}
int dfs(int u)
{
    int v,sum=0;
    for(int i=head[u]; i; i=e[i].next)
    {
        v=e[i].to;
        if(!vis[v])
        {
            vis[v]=1;
            sum+=dfs(v);
        }
    }
    if(sum>=2)
    {
        if(u==1) ans=ans+2*(sum-2);
        else ans=ans+2*(sum-1);
        return 0;
    }
    return 1;
}
int main()
{

    cin>>n;
    while(n--)
    {
        cin>>m;
        cnt=0;
        for(int i=1; i<m; i++)
        {
            int x,y;
            cin>>x>>y;
            add(x,y);
            add(y,x);//无向图
        }
        ans=0;
        vis[1]=1;
        dfs(1);
        cout<<ans+1<<endl;
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/iloveysm/p/12323661.html