zoukankan      html  css  js  c++  java
  • 2018宁夏邀请赛G(DFS,动态规划【VECTOR<PAIR>】)

    //代码跑的很慢四秒会超时,结尾附两秒代码(标程)
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll inf=0x3f3f3f3f;
    vector<pair<int,int>>tree[100010];
    ll dp[100010][110];/*dp[u][i]表示u节点为根的子树上选择了i个叶子节点,
    会经过u这个子树的边的权值和的最优值。转移方程如下:
    dp[u][i]=min( dp[u][i-j]+dp[v][j]+w*j*(k-j) );
    v是u的子节点,w是u与v之间边的权值,l*(k-l)表示的是这条边会被经过的次数
    (j为从v这个树上过来的叶节点数,k-j为其它地方选择的叶节点数)*/
    int siz[100010];
    int t,n,k;
    void dfs(int u,int f)
    {
        if(tree[u].size()==1)
        {
            dp[u][0]=0;
            dp[u][1]=0;
            siz[u]=1;//记录叶子节点数量
            return;
        }
        siz[u]=0;
        dp[u][0]=0;
        for(int i=0;i<tree[u].size();i++)
        {
            int v=tree[u][i].first;//联接点
            int w=tree[u][i].second;//权重
            if(v==f)
                continue;
            dfs(v,u);
            siz[u]+=siz[v];
            dp[u][k]=min(dp[u][k],dp[v][k]);//在v上选了k个叶子
            for(int j=min(k,siz[u]);j>=1;j--)//限制j最大为k
            {
                for(int l=1;l<=min(j,siz[v]);l++)
                    dp[u][j]=min(dp[u][j],dp[u][j-l]+dp[v][l]+l*(k-l)*w);//状态转移方程
            }
        }
    }
    int main()
    {
        scanf("%d",&t);
        for(int tt=1;tt<=t;tt++)
        {
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
                tree[i].clear();
            for(int i=1;i<n;i++)
            {
                int u,v;
                int w;
                scanf("%d%d%lld",&u,&v,&w);
                tree[u].push_back({v,w});
                tree[v].push_back({u,w});
            }
            printf("Case #%d: ",tt);
            if(n==2)
                printf("%d ",(k==2?tree[1][0].second:0));//当且仅当k==2时存在一条路的长度
            else
            {
                int rt=0;
                for(int i=1;i<=n;i++)
                    if(tree[i].size()>1)//找到一个不为叶子节点的节点作根
                    {
                        rt=i;
                        break;
                    }
                for(int i=1;i<=n;i++)
                {
                    dp[i][0]=0;
                    for(int j=1;j<=k;j++)
                        dp[i][j]=inf;
                }
                dfs(rt,0);
                printf("%lld ",dp[rt][k]);
            }
        }
        return 0;
    }
     /*标程AC代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN=100005;
    const int MAXK=105;
    const ll INF=(1LL<<60)-1;
    vector<pair<int,int> > e[MAXN];
    ll dp[MAXN][MAXK],tmp[MAXK];
    int sz[MAXN];
    void dfs(int u,int f,int k)
    {
        if((int)e[u].size()==1)
        {
            sz[u]=1,dp[u][0]=dp[u][1]=0;
            return;
        }
        sz[u]=0;
        for(auto &t:e[u])
        {
            int v=t.first,c=t.second;
            if(v==f)continue;
            dfs(v,u,k);
            int ts=min(k,sz[u]+sz[v]);
            for(int i=0;i<=ts;i++)
                tmp[i]=INF;
            for(int i=0;i<=sz[u];i++)
                for(int j=0;j<=sz[v] && i+j<=ts;j++)
                    tmp[i+j]=min(tmp[i+j],dp[u][i]+dp[v][j]+j*(k-j)*c);
            for(int i=0;i<=ts;i++)
                dp[u][i]=tmp[i];
            sz[u]=ts;
        }
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int ca=1;ca<=T;ca++)
        {
            int n,k;
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n-1;i++)
            {
                int u,w,v;
                scanf("%d%d%d",&u,&v,&w);
                e[u].push_back({v,w});
                e[v].push_back({u,w});
            }
            printf("Case #%d: ",ca);
            if(n==2)printf("%d ",(k==2 ? e[1][0].second : 0));
            else
            {
                int rt=0;
                for(int i=1;i<=n;i++)
                    if((int)e[i].size()>1)rt=i;
                assert(rt);
                dfs(rt,0,k);
                printf("%lld ",dp[rt][k]);
            }
            for(int i=1;i<=n;i++)
                e[i].clear();
        }
        return 0;
    }
    */
    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    MVC————前台中,冒号与等号的区别
    MVC-通过对象获取整个表单内容
    对Webservice的理解
    windows上使用logstash-input-jdbc
    elasticsearch-head的安装和使用
    最简单的php学习
    linq to sql 和linq to php 的区别
    thinkphp中JS文件不能写__ROOT__变量
    用curl获取https请求时出现错误的处理
    优化apk的odex处理
  • 原文地址:https://www.cnblogs.com/ldudxy/p/9502542.html
Copyright © 2011-2022 走看看