zoukankan      html  css  js  c++  java
  • CF1293E-Xenon's Attack on the Gangs 树状DP

    0边把图分成两个部分,这两个部分的路径之间,mex起码为1,都对答案产生1的贡献。

    然后1边接在0边旁边,把图分成了更小的两个部分(0,1的两端),和一些不会再产生新的贡献的区域,这两个更小的部分路径之间,mex起码为2,都对答案又产生了1的贡献。(他们在刚刚算mex起码为1的时候,已经贡献过1了,所以再贡献1,mex就起码为2了)。

    依次类推,我们发现最后只有一条链上的边放置的是有意义的,其他边都可以随便放,反正不会产生贡献。

    我们考虑这种情况下如何求解。

    如果只考虑一条链,dp[i][j]从i边开始到j边 结束,放置0~(j-i)这些边的最大贡献。dp[i][j] = lcnt[i] * rcnt[j] + max(dp[i + 1][j],dp[i][j - 1])。

    这道题允许O(N^2)做法,所以我们可以枚举每条链,然后用这个DP就行了。

    siz[i][root]以root为根,i的孩子有多少。fa[i][root]以root为根,i的父亲是谁。

    dp[x][y]就是把x和y之间的路径放置的最大贡献。和上面转移是一样的,只不过看 x的时候,就把y当根,来使得所计算的贡献都是正确的。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 const int MAXN = 3100;
     7 int cnt,n;
     8 int head[MAXN],siz[MAXN][MAXN],fa[MAXN][MAXN],nxt[2 * MAXN],to[2 * MAXN];
     9 ll dp[MAXN][MAXN],ans;
    10 void add(int x,int y)
    11 {
    12     nxt[++cnt] = head[x];
    13     to[cnt] = y;
    14     head[x] = cnt;
    15 }
    16 void dfs(int x,int root)
    17 {
    18     siz[x][root] = 1;
    19     for (int i = head[x];i;i = nxt[i])
    20     {
    21         if (to[i] == fa[x][root])
    22             continue;
    23         fa[to[i]][root] = x;
    24         dfs(to[i],root);
    25         siz[x][root] += siz[to[i]][root];
    26     }
    27 }
    28 ll dfs2(int x,int y)
    29 {
    30     if (dp[x][y] != -1)
    31         return dp[x][y];
    32     return dp[x][y] = siz[x][y] * siz[y][x] + max(dfs2(x,fa[y][x]),dfs2(fa[x][y],y));
    33 }
    34 int main()
    35 {
    36     scanf("%d",&n);
    37     int tu,tv;
    38     for (int i = 1;i <= n - 1;i++)
    39     {
    40         scanf("%d%d",&tu,&tv);
    41         add(tu,tv);
    42         add(tv,tu); 
    43     }
    44     memset(dp,-1,sizeof(dp));
    45     for (int i = 1;i <= n;i++)
    46         dp[i][i] = 0;
    47     for (int i = 1;i <= n;i++)
    48         dfs(i,i);
    49     for (int i = 1;i <= n;i++)
    50         for (int j = 1;j <= n;j++)
    51             ans = max(ans,dfs2(i,j));
    52     printf("%lld
    ",ans);
    53     return 0;
    54 }
  • 相关阅读:
    WebSocket
    Spring Web MVC
    对象关系映射(ORM)数据访问
    使用JDBC进行数据访问
    【Mysql】【基础综合题解】大一下学期数据库综合训练题解
    【Mysql】【解决问题】[Err] 1055
    【JavaSE】【IO流】复制单级或多级文件夹
    C#使用FFmpeg的总结
    C#一个IM系统简单总结
    重新开启博客
  • 原文地址:https://www.cnblogs.com/iat14/p/12290105.html
Copyright © 2011-2022 走看看