• 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;
    }
    
  • 相关阅读:
    MongoDB结构划分
    iphone下scrollview图片浏览器小记
    图文详解linux/windows mysql忘记root密码解决方案
    【记】Javascript遍历对象属性的方法
    【jQuery】jQueryUI中的datepicker在overflow下的两点点小小的问题。
    第一个测试文章
    【记】Javascript的正则表达式RegExp
    【记】IE下input标签中的paddingleft和paddingright
    【CSS】关于IE、FireFox中table强制换行的总结
    【DOCTYPE】兼容模式和标准模式
  • 原文地址:https://www.cnblogs.com/tarjan/p/7624187.html
Copyright © 2020-2023  润新知