【题意】
基环树上的最大点权独立集
【分析】
我们采用删去环上的一条边的方式来计算
因为一棵树上的最大点权独立集我们很熟练,所以问题就是删去的那条边的贡献
图源 https://www.luogu.com.cn/blog/ShadderLeave/ji-huan-shu-bi-ji
考虑删去的边连接了lt和rt
我们只需要考虑强制规定lt和rt不能同时选
这样我们分别从lt和rt计算两次取max即可
【代码】
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+5; int n,head[maxn],tot,fa[maxn]; struct edge { int to,nxt; }e[maxn<<1]; void add(int x,int y) { e[++tot].to=y; e[tot].nxt=head[x]; head[x]=tot; } int p[maxn]; int find(int x) { if(x==fa[x]) return x; return fa[x]=find(fa[x]); } int f[maxn][2]; void dfs(int u,int fa) { f[u][1]=p[u]; for(int i=head[u];i;i=e[i].nxt) { int to=e[i].to; if(to==fa) continue; dfs(to,u); f[u][0]+=max(f[to][1],f[to][0]); f[u][1]+=f[to][0]; } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&p[i]),fa[i]=i; int x,y,lt,rt; for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); x++; y++; int fx=find(x),fy=find(y); if(fx==fy) {lt=x,rt=y; continue;} add(x,y); add(y,x); fa[fx]=fy; } int ans=0; dfs(rt,0); ans=max(ans,f[rt][0]); memset(f,0,sizeof(f)); dfs(lt,0); ans=max(ans,f[lt][0]); double k; scanf("%lf",&k); printf("%.1f",ans*k); return 0; }