zoukankan      html  css  js  c++  java
  • POJ 1848 Tree

    Tree

    Time Limit: 1000ms
    Memory Limit: 30000KB
    This problem will be judged on PKU. Original ID: 1848
    64-bit integer IO format: %lld      Java class name: Main
     
    Consider a tree with N vertices, numbered from 1 to N. Add, if it is possible, a minimum number of edges thus every vertex belongs to exactly one cycle.
     

    Input

    The input has the following structure: 

    x(1) y(1) 
    x(2) y(2) 
    ... 
    x(N-1) y(n-1) 
    N (3 <= N <=100) is the number of vertices. x(i) and y(i) (x(i), y(i) are integers, 1 <= x(i), y(i) <= N) represent the two vertices connected by the i-th edge. 
     

    Output

    The output will contain the value -1 if the problem doesn't have a solution, otherwise an integer, representing the number of added edges.
     

    Sample Input

    7
    1 2
    1 3
    3 5
    3 4
    5 6
    5 7
    

    Sample Output

    2

    Source

     
    解题:树形dp
     

    本题有三种状态,分别是
    dp[u][0],以u为根,所有的点都在环内
    dp[u][1],以u为根,除了u外其余的都在环内
    dp[u][2],以u为根,除了u和与u点相连的链(至少有两个点)外,其余的点都在环内
    有四种状态转移
    1、所有子节点都满足在环内,只有根节点不在环内,
    dp[u][1]=min(INF,sum);(sum是所有的dp[v][0]的和)
    2、有一个子节点不在环内,以该子节点有一条链,将此链连到以u为根的树上,(+1)就可以使得u的所有子节点都在环内
    dp[u][0]=min(dp[u][0],sum-dp[v][0]+dp[v][2]+1);
    3、有一个子节点不在环内,其余自己处理,
    dp[u][2]=min(dp[u][2],sum-dp[v][0]+min(dp[v][1],dp[v][2]));
    4、有两个不在环内,将这两个加一条边连起来就可使得所有都在环内
    dp[u][0]=min(dp[u][0],sum-dp[v][0]-dp[k][0]+min(dp[v][1],dp[v][2])+min(dp[k][1],dp[k][2])+1);

    看来别人的解释,还是很好理解的

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <vector>
     5 using namespace std;
     6 const int INF = 10010;
     7 const int maxn = 200;
     8 vector<int>g[maxn];
     9 int dp[maxn][3];
    10 void dfs(int u,int fa){
    11     int sum = 0;
    12     dp[u][0] = dp[u][1] = dp[u][2] = INF;
    13     for(int i = g[u].size()-1; i >= 0; --i){
    14         if(g[u][i] == fa) continue;
    15         dfs(g[u][i],u);
    16         sum += dp[g[u][i]][0];
    17     }
    18     dp[u][1] = sum;
    19     for(int i = g[u].size()-1; i >= 0; --i){
    20         if(g[u][i] == fa) continue;
    21         dp[u][0] = min(dp[u][0],sum - dp[g[u][i]][0] + dp[g[u][i]][2] + 1);
    22         dp[u][2] = min(dp[u][2],sum - dp[g[u][i]][0] + min(dp[g[u][i]][1],dp[g[u][i]][2]));
    23         for(int j = g[u].size()-1; j >= 0; --j){
    24             if(g[u][j] != g[u][i] && g[u][j] != fa)
    25                 dp[u][0] = min(dp[u][0],sum - dp[g[u][i]][0] - dp[g[u][j]][0]
    26                                + min(dp[g[u][i]][1],dp[g[u][i]][2]) + min(dp[g[u][j]][1],dp[g[u][j]][2]) + 1);
    27         }
    28     }
    29 }
    30 int main(){
    31     int n,u,v;
    32     while(~scanf("%d",&n)){
    33         for(int i = 0; i < maxn; ++i) g[i].clear();
    34         for(int i = 1; i < n; ++i){
    35             scanf("%d%d",&u,&v);
    36             g[u].push_back(v);
    37             g[v].push_back(u);
    38         }
    39         dfs(1,-1);
    40         printf("%d
    ",dp[1][0] >= INF?-1:dp[1][0]);
    41     }
    42     return 0;
    43 }
    View Code
  • 相关阅读:
    [转载]Oracle查看当前用户权限
    [转载]Oracle查看当前用户权限
    UltraEdit实用技巧
    _splitpath,_makepath分析路径
    [ZT]让你的软件界面更漂亮(1、2)
    [book]程序员修炼之道
    考考你的C++水平
    将*.STL转换成顶点索引格式
    JBuilder 2006 企业完整版
    [book]道法自然
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4800024.html
Copyright © 2011-2022 走看看