zoukankan      html  css  js  c++  java
  • POJ1848--Tree ——树形dp

    题意:给你一个树,问你最少连几条边可以让树中的每一个节点在且只在一个环内。如果无法完成就输出-1。

    我们设dp[i][0]为根节点为i的树变成每一个节点都在且只在一个环里所需要的最小边数。dp[i][1]为除了根节点i外其他点都在且只在一个环里所需要的最小边数。

    dp[i][2]为除了根节点和一个子节点(以及子节点可有可无的链)都在且只在一个环里所需要的最小边数。

    这样我们的状态转移需要考虑以下4种情况:

    (第一张图最上面应该是dp[i][1]  当时写错了不好改)

      

    具体代码如下:

    #include<iostream>
    #include<vector>
    using namespace std;
    #define ll long long
    const ll inf=100000000;
    ll dp[105][3];
    vector<int> a[105];
    void solve(int u,int f)
    {
        int i,j;
        if(a[u].size()==1&&a[u][0]==f)
        {
            dp[u][0]=inf;
            dp[u][1]=0;
            dp[u][2]=inf;
            //
            return;
        }
        for(i=0;i<a[u].size();i++)
        {
            if(a[u][i]==f) continue;
            solve(a[u][i],u);
        }
        ll sum=0; 
        for(i=0;i<a[u].size();i++)
        {
            if(a[u][i]==f) continue;
            sum+=dp[a[u][i]][0];
        }
        dp[u][1]=min(dp[u][1],sum);
        for(i=0;i<a[u].size();i++)
        {
            if(a[u][i]==f) continue;
            ll now=sum-dp[a[u][i]][0]+min(dp[a[u][i]][1],dp[a[u][i]][2]);
            ll now1=sum-dp[a[u][i]][0]+dp[a[u][i]][2]+1;
            dp[u][2]=min(dp[u][2],now);
            dp[u][0]=min(dp[u][0],now1);
        }
        for(i=0;i<a[u].size()-1;i++)
        for(j=i+1;j<a[u].size();j++)
        {
            if(a[u][i]==f||a[u][j]==f) continue;
            ll now=1+sum-dp[a[u][i]][0]-dp[a[u][j]][0]+min(dp[a[u][i]][1],dp[a[u][i]][2])+min(dp[a[u][j]][1],dp[a[u][j]][2]);
            //cout<<u<<i<<j<<" "<<min(dp[a[u][i]][1],dp[a[u][i]][2])<<" "<<min(dp[a[u][j]][1],dp[a[u][j]][2])<<endl;
            dp[u][0]=min(dp[u][0],now);
        }
        
    }
    
    int main()
    {
        int i,n,x,j,y;
        cin>>n;
        for(i=0;i<n-1;i++) 
        {
            cin>>x>>y;
            a[x].push_back(y);
            a[y].push_back(x);
        }
        for(i=1;i<=n;i++)
        for(j=0;j<=2;j++) dp[i][j]=inf;
        solve(1,-1);
        ll ans=inf;
        ans=dp[1][0];
        if(ans==inf) cout<<"-1"<<endl;
        else cout<<ans<<endl;
        //for(i=1;i<=n;i++) cout<<dp[i][0]<<" "<<dp[i][1]<<" "<<dp[i][2]<<endl;
    }
  • 相关阅读:
    Python 3 socket 编程
    Python 3 面向对象进阶
    python 3 封装
    Python 3 接口与归一化设计
    JS 的5个不良编码习惯
    Java基础(三)选择结构
    Java基础(二)变量和数据类型
    vue的注意规范之v-if 与 v-for 一起使用
    从Vue的DOM构建机制中理解key
    Vue内部怎样处理props选项的多种写法
  • 原文地址:https://www.cnblogs.com/wsblm/p/10741774.html
Copyright © 2011-2022 走看看