C. Xenon's Attack on the Gangs(树形dp)

http://codeforces.com/problemset/problem/1292/C

题意:

给出一棵树,n个点,你将0至n-2这n-1个数填到每条边上。一条路径的权值为最小的没有出现过的自然数,求所有路径的权值和的最大值。

解析:

没有出现过的自然数,可以这么理解,如果这条路径上包含了0、1,那么权值为2。

也就是说,答案变为:包含0的路径数+包含01的路径数+包含012的路径数+……

那么考虑dp[x][y]表示将数填到x到y这条路的最大值

在这里插入图片描述
d p [ X ] [ Y ] = m a x ( d p [ X ] [ K ] , d p [ Q ] [ Y ] ) + s i z X s i z Y dp[X][Y]=max(dp[X][K],dp[Q][Y])+siz_X\cdot siz_Y


先把长度为1的链放队列再做bfs,不断延长即可。

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-01-25-14.52.27
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=3e3+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

int n;
#define rep_e(i,p,u) for(int i=head[p],u=to[i];i;i=nex[i],u=to[i])
int head[maxn],to[maxn<<1],nex[maxn<<1],now;
void add(int a,int b){
    nex[++now]=head[a];head[a]=now;to[now]=b;
}
void init_edge(){
    memset(head,0,sizeof head);
    now=0;
}
/*_________________________________________________________edge*/

int siz[maxn],fa[maxn];
struct node{
    int x,y,top,son;
    node(int x,int y,int top,int son):x(x),y(y),top(top),son(son){}
    node(){}
};
vector<node>V;
void dfs0(int p,int _fa){
    siz[p]=1;
    rep_e(i,p,u){
        if(u==_fa)continue;
        V.push_back(node(p,u,p,u));
        fa[u]=p;
        dfs0(u,p);
        siz[p]+=siz[u];
    }
}

queue<node>Q;
LL dp[maxn][maxn];
void bfs(){
    for(auto P:V){
        dp[P.x][P.y]=dp[P.y][P.x]=(siz[1]-siz[P.son])*siz[P.son];
        Q.push(P);
    }
    // x up,y down
    while(!Q.empty()){
        node P=Q.front();Q.pop();
        if(P.top!=-1){
        	// 往上
            if(P.x!=1){
                LL add=(siz[1]-siz[P.x])*siz[P.y];
                if(dp[fa[P.x]][P.y]==0)Q.push(node(fa[P.x],P.y,fa[P.x],P.x));
                dp[fa[P.x]][P.y]=dp[P.y][fa[P.x]]=max(dp[P.y][fa[P.x]],dp[P.x][P.y]+add);
            }
            rep_e(i,P.x,u){
                if(u==P.son||u==fa[P.x])continue;
                LL add=siz[u]*siz[P.y];
                if(dp[u][P.y]==0)Q.push(node(u,P.y,-1,-1));
                dp[u][P.y]=dp[P.y][u]=max(dp[P.y][u],dp[P.x][P.y]+add);
            }
            rep_e(i,P.y,u){
                if(u==fa[P.y])continue;
                LL add=(siz[1]-siz[P.son])*siz[u];
                if(dp[P.x][u]==0)Q.push(node(P.x,u,P.x,P.son));
                dp[P.x][u]=dp[u][P.x]=max(dp[u][P.x],dp[P.x][P.y]+add);
            }
        }
        else{
            rep_e(i,P.y,u){
                if(u==fa[P.y])continue;
                LL add=siz[P.x]*siz[u];
                if(dp[P.x][u]==0)Q.push(node(P.x,u,-1,-1));
                dp[P.x][u]=dp[u][P.x]=max(dp[u][P.x],dp[P.x][P.y]+add);
            }
            rep_e(i,P.x,u){
                if(u==fa[P.x])continue;
                LL add=siz[P.y]*siz[u];
                if(dp[P.y][u]==0)Q.push(node(P.y,u,-1,-1));
                dp[P.y][u]=dp[u][P.y]=max(dp[u][P.y],dp[P.x][P.y]+add);
            }
        }
    }
}

int main(){
    n=rd;
    rep(i,1,n-1){
        int a=rd,b=rd;
        add(a,b);add(b,a);
    }
    dfs0(1,-1);
    bfs();
    LL mx=0;
    rep(i,1,n)rep(j,1,n)mx=max(mx,dp[i][j]);
    printf("%lld\n",mx);
    return 0;
}

/*_________________________________________________________end*/

发布了723 篇原创文章 · 获赞 314 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104083500