• HDU-4714-贪心


    Tree2cycle

    Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
    Total Submission(s): 3091    Accepted Submission(s): 719


    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
           求将一棵树拆分为一个环的最小的代价,可以拆解边和增加边,代价都是1.
         换一下思路,就是把这棵树拆掉det条边形成了det+1条链,再添加det+1条边,总代价就是det*2+1;我们只要求出最小的det就ok了。
    对于节点u它可能有一个或多个儿子,如果只有一个儿子的话那就是一条链,不用再管,如果有son个儿子(son>1),我们需要拆掉son-1条边才能保证拆分成链,问题在于应该怎么拆掉这son-1条链才能最优。
                fa           
                 |
        u
        /  |      
          v1  v2   v3
        对于上面这棵树,我们可以选择拆掉u-v2和u-v3或者是u-fa和u-v1,也就是删掉两个儿子或者一个儿子和一个父亲,会发现后者其实更优,因为避免了父亲形成多儿子的情况,就减少了删除的边数。知道这点就很容易了,递归返回儿子数目即可。
        
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define inf 0x3f3f3f3f
     7 #pragma comment(linker, "/STACK:102400000,102400000")
     8 int first[1000010],tot;
     9 struct Edge
    10 {
    11     int v,next;
    12 }e[2001000];
    13 void add(int u,int v){
    14     e[tot].v=v;
    15     e[tot].next=first[u];
    16     first[u]=tot++;
    17 }
    18 int aaa;
    19 int dfs(int u,int fa)
    20 {
    21     int s=0;
    22     for(int i=first[u];~i;i=e[i].next){
    23         int v=e[i].v;
    24         if(v==fa) continue;
    25         s+=dfs(v,u);
    26     }
    27     if(s>1){
    28         aaa+=s-1;
    29         if(u==1) aaa--;
    30         return 0;
    31     }
    32     else {
    33         return 1;
    34     }
    35 }
    36 int main()
    37 {
    38     int n,i,j,k,u,v;
    39     int t;
    40     cin>>t;
    41     while(t--){aaa=0;
    42         memset(first,-1,sizeof(first));
    43         tot=0;
    44         scanf("%d",&n);
    45         for(i=1;i<n;++i){
    46             scanf("%d%d",&u,&v);
    47             add(u,v);
    48             add(v,u);
    49         }
    50         dfs(1,0);
    51         cout<<aaa+aaa+1<<endl;
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    后台服务器经典面试题
    Java英语面试题(核心知识篇)
    Java常用英语汇总(面试必备)
    字符压缩编码
    外排序
    基数排序
    Windows Server 2008 R2 部署服务
    LINUX中常用操作命令
    我的学习笔记_Windows_HOOK编程 2009-12-03 11:19
    CSDN-Code平台使用过程中的5点经验教训
  • 原文地址:https://www.cnblogs.com/zzqc/p/8872420.html
Copyright © 2020-2023  润新知