zoukankan      html  css  js  c++  java
  • hdu 5534 Partial Tree(dp+降唯,好题)

    题目链接

    Partial Tree

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 1577 Accepted Submission(s): 789

    Problem Description
    In mathematics, and more specifically in graph theory, a tree is an undirected graph in which any two nodes are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.

    You find a partial tree on the way home. This tree has n nodes but lacks of n−1 edges. You want to complete this tree by adding n−1 edges. There must be exactly one path between any two nodes after adding. As you know, there are nn−2 ways to complete this tree, and you want to make the completed tree as cool as possible. The coolness of a tree is the sum of coolness of its nodes. The coolness of a node is f(d), where f is a predefined function and d is the degree of this node. What's the maximum coolness of the completed tree?

    Input
    The first line contains an integer T indicating the total number of test cases.
    Each test case starts with an integer n in one line,
    then one line with n−1 integers f(1),f(2),…,f(n−1).

    1≤T≤2015
    2≤n≤2015
    0≤f(i)≤10000
    There are at most 10 test cases with n>100.

    Output
    For each test case, please output the maximum coolness of the completed tree in one line.

    Sample Input
    2
    3
    2 1
    4
    5 1 4

    Sample Output
    5
    19

    Source
    2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)

    Recommend
    hujie | We have carefully selected several similar problems for you: 6216 6215 6214 6213 6212

    题意:

    给出 (N) 个结点我们需要添加 (N-1) 条边使得它变成一棵树,定义一个函数 (f(x)) ,给出它(f(1),f(2)...f(N-1)) 的值,一个度为 (d) 的结点的炫酷值是 (f(d)),一棵树的炫酷值是所有结点的炫酷值之和,问 (N) 个结点的树的最大炫酷值。

    题解:

    有个定理:如果对 (N) 个结点指定其度,而且每个度都大于0且所有结点度之和为 (2 imes N-2),那么能够构造出满足的一棵树。

    那么问题就转化为(假设度为 (i) 的点有 (x_i) 个)

    (sum x_i=N)

    (sum x_i imes i=2 imes N-2)

    (max(f(i) imes x_i))

    很容易想到一个 (O(N^3))(dp) ,令 (d[i][j]) 表示分配了 (i) 个点度数和为 (j) 的最大炫酷值,那么答案就是 (d[N][N*2-2])。可是会超时。

    由于要给每个点都分配度数,且度数大于等于1,这一个限制使得 (dp) 方程多了一维,因此我们可以先将每个结点分配度为1,每个 (f(i)-f(1)),此时问题相当于一个完全背包,(O(N^2)) 可解。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    #define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int inf=0x3fffffff;
    const ll mod=1000000007;
    const int maxn=2017+10;
    int d[maxn][maxn];
    int v[maxn];
    int main()
    {
        int cas;
        scanf("%d",&cas);
        while(cas--)
        {
            int n;
            scanf("%d",&n);
            rep(i,1,n) scanf("%d",&v[i]);
            rep(i,2,n) v[i]-=v[1];
            int ans=n*v[1];
            v[1]=0;
            rep(i,0,n) rep(j,0,n-1) d[i][j]=-1e9;
            d[0][0]=0;
            rep(i,1,n) rep(j,0,n-1)
            {
                d[i][j]=d[i-1][j];
                if(j>=i-1)
                    d[i][j]=max(d[i][j],d[i][j-i+1]+v[i]);
            }
            ans+=d[n-1][n-2];
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    

    滚动数组:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    #define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int inf=0x3fffffff;
    const ll mod=1000000007;
    const int maxn=2017+10;
    int d[maxn];
    int v[maxn];
    int main()
    {
        int cas;
        scanf("%d",&cas);
        while(cas--)
        {
            int n;
            scanf("%d",&n);
            rep(i,1,n) scanf("%d",&v[i]);
            rep(i,2,n) v[i]-=v[1];
            int ans=n*v[1];
            v[1]=0;
            rep(j,0,n-1) d[j]=-1e9;
            d[0]=0;
            rep(i,1,n) rep(j,0,n-1)
            {
                //d[i][j]=d[i-1][j];
                if(j>=i-1)
                    d[j]=max(d[j],d[j-i+1]+v[i]);
            }
            ans+=d[n-2];
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Spring Boot (20) 拦截器
    Spring Boot (19) servlet、filter、listener
    Spring Boot (18) @Async异步
    Spring Boot (17) 发送邮件
    Spring Boot (16) logback和access日志
    Spring Boot (15) pom.xml设置
    Spring Boot (14) 数据源配置原理
    Spring Boot (13) druid监控
    Spring boot (12) tomcat jdbc连接池
    Spring Boot (11) mybatis 关联映射
  • 原文地址:https://www.cnblogs.com/tarjan/p/7624187.html
Copyright © 2011-2022 走看看