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;
    }
  • 相关阅读:
    jquery ajax 后台响应成功,返回正确json但不执行success方法,执行error的问题
    bootstrap轮播组件,大屏幕图片居中效果
    mouseover和mouseout事件在鼠标经过子元素时也会触发
    vertical-align的深入学习
    小技巧
    css字体大小设置em与rem的区别
    子元素的margin-top影响父元素原因和解决办法
    JavaScript随机打乱数组
    JavaScript 获取当月天数
    javaScript 的option触发事件
  • 原文地址:https://www.cnblogs.com/wsblm/p/10741774.html
Copyright © 2011-2022 走看看