zoukankan      html  css  js  c++  java
  • codeforces#1293E. Xenon's Attack on the Gangs(树上dp)

    题目链接:

    https://codeforces.com/contest/1293/problem/E

    题意:

    给出一颗节点数为$n$的树,可以给它的每条边赋从$0$到$n-1$的值,不能重复赋值

    定义$mex(u,v)$为从节点$u$到$v$的最短路径中没有出现的权值的最小整数

    计算下面等式的最大值:

    $$S = sum_{1 leq u < v leq n} mex(u, v)$$

    
    

    分析:

    根据以下等式:

    $$S = sum_{1 leq u < v leq n} mex(u, v) = sum_{1 leq x leq n} left( sum_{mex(u, v) = x} x ight) = sum_{1 leq x leq n} left( sum_{mex(u, v) geq x} 1 ight) = sum_{1 leq x leq n} f(x)$$

    我们只需要依次计算$f(x)$即可,$f(x)$为路径上包括权值$0$到$x-1$的节点对数

     定义$dp[u][v]$为,假设$u$到$v$的长度为$l$,把$0$到$l-1$都填充入$u$到$v$的路径的最大值,不计算$l$到$n-1$权值的贡献

     显然,$l-1$只有两种填充情况,在$u$附近或者$v$附近

     定义$sub(u,v)$为,以$u$为根节点时,$v$的子树大小

     定义$par(u,v)$为,以$u$为根节点时,$v$的父节点

     $$dp[u][v] = sub(u, v) imes sub(v, u) + max(dp[par(v, u)][v], dp[u][par(u, v)])$$

     AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for (int i=a;i<=b;i++)
    #define per(i,a,b) for (int i=b;i>=a;i--)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    
    typedef long long ll;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    
    const ll mod=1e5+7;
    const int maxn=3e3+7;
    
    ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
    
    VI ve[maxn];
    int par[maxn][maxn],sub[maxn][maxn];
    int root,n;
    ll dp[maxn][maxn];
    void dfs(int x,int fa){
        par[root][x]=fa;
        sub[root][x]=1;
        for(auto i:ve[x]){
            if(i==fa)continue;
            dfs(i,x);
            sub[root][x]+=sub[root][i];
        }
    }
    ll getdp(int u,int v){
        if(u>v)swap(u,v);
        if(dp[u][v]!=-1)return dp[u][v];
        if(u==v)return 0;
        dp[u][v]=max(getdp(u,par[u][v]),getdp(v,par[v][u]))+sub[u][v]*sub[v][u];
        return dp[u][v];
    }
    int main() {
        scanf("%d",&n);
        rep(i,1,n-1){
            int a,b;
            scanf("%d %d",&a,&b);
            ve[a].pb(b);
            ve[b].pb(a);
        }
        rep(i,1,n){
            root=i;
            dfs(i,-1);
        }
        memset(dp,-1,sizeof(dp));
        ll ans=0;
        rep(i,1,n){
            rep(j,i+1,n){
                ans=max(ans,getdp(i,j));
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    多线程(10) — Future模式
    Java的设计模式(7)— 生产者-消费者模式
    多线程(9) — 无锁
    多线程(8) — ThreadLocal
    Java的设计模式(6)— 模板模式
    多线程(7)— JDK对锁优化的努力
    多线程(6) — 提高锁性能的一些看法
    复位电路 解析
    C语言数据类型
    MSP下载方式
  • 原文地址:https://www.cnblogs.com/carcar/p/12448220.html
Copyright © 2011-2022 走看看