1 条题解

  • 1
    @ 2023-10-31 10:35:40

    具体思路

    nn 个点 nn 条边显然是基环树。

    我们先考虑普通的树形 dp。

    fx,0/1f_{x,0/1} 表示以 xx 为根的子树内, xx 节点不选或选的最大战斗力总和。

    $$f_{x,0}=\sum \max \limits_{y \in son_x} \{f_{y,0},f_{y,1} \} $$fx,1=ysonxfy,0f_{x,1}=\sum_{y \in son_x}f_{y,0}

    xx 不选的话,xx 的儿子选或不选都行,xx 选的话,xx 的儿子都不能选。

    考虑环的影响。

    设环的两个端点分别为 x,yx,y

    • edge(x,y)edge(x,y) 无影响:
      1. xx 选,yy 不选。
      2. xx 不选,yy 选或不选。
    • edge(x,y)edge(x,y) 有影响:
      1. xx 选,yy 选。

    对于 x,yx,y 同时选的情况,我们需要强制 xx 不选或 yy 不选。

    即跑一遍以 xx 为根的树形 dp,跑一遍以 yy 为根的树形 dp。

    ans=max{fx,0,fy,0}ans=\max \{ f_{x,0},f_{y,0} \}

    注意:

    • 不保证连通,有可能是基环树森林。
    • 要建无向边,有向边的话你从另一个端点出发就走不了了。
    • 可以用并查集维护连通性来求出每个基环树森林环的两个端点。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>PII;
    const int N=1e6+5;
    struct edge{
    	int x,y,pre;
    }a[2*N];
    int last[N],alen;
    void ins(int x,int y){
    	a[++alen]=edge{x,y,last[x]};
    	last[x]=alen;
    }
    int fa[N];
    int get(int x){
    	if(fa[x]==x)return x;
    	return fa[x]=get(fa[x]);
    }
    vector<PII>root;
    int w[N];LL f[N][2];
    void treedp(int x,int fa){
    	f[x][0]=0,f[x][1]=w[x];
    	for(int k=last[x];k;k=a[k].pre){
    		int y=a[k].y;
    		if(y==fa)continue;
    		treedp(y,x);
    		f[x][0]+=max(f[y][0],f[y][1]);
    		f[x][1]+=f[y][0];
    	}
    }
    int main(){
    	int n;scanf("%d",&n);
    	alen=1;memset(last,0,sizeof(last));
    	for(int i=1;i<=n;i++){
    		fa[i]=i;
    	}
    	for(int x=1;x<=n;x++){
    		int y;scanf("%d%d",&w[x],&y);
    		int tx=get(x),ty=get(y);
    		if(tx==ty){
    			root.push_back({x,y});
    		}
    		else{
    			fa[tx]=ty;
    			ins(x,y),ins(y,x);
    		}
    	}
    	LL ans=0;
    	for(auto i:root){
    		int x=i.first,y=i.second;
    		LL res=0;
    		treedp(x,0);
    		res=max(res,f[x][0]);
    		treedp(y,0);
    		res=max(res,f[y][0]);
    		ans=ans+res;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    1040
    时间
    1000ms
    内存
    162MiB
    难度
    6
    标签
    (无)
    递交数
    87
    已通过
    27
    上传者