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;
    }
  • 相关阅读:
    css选择器的分类及优先级计算方法总结
    第四周实验总结&实验报告
    2019春季总结
    第七周课程总结&实验报告五
    第六周学习总结&java实验报告四
    第二周Java学习总结
    第九周课程总结&实验报告(七)
    第五周学习总结&实验报告三
    第三周课程总结及实验报告
    第八周课程总结&实验报告(六)
  • 原文地址:https://www.cnblogs.com/wsblm/p/10741774.html
Copyright © 2011-2022 走看看