仙人掌暂时不会,只好来水一水基环外向树。
话说无向的到底应该怎么叫?外向?内向?基环无向树(太诡异了)?
然后对于这道题,由于是基环,所以要拆掉环上的一条边(u,v)
然后树形DP
u不选,dp。
v不选,dp。
取两者的最大值加到ans里去。
然后我很沙茶地把当前点i当成了根,跪了好几次。
#include<iostream> #include<cstdio> #include<cstring> usingnamespace std; constint N=1000000+5; typedeflong long ll; structEdge{intto,next;}e[N*2]; ll dp[N][2],val[N]; inthead[N],cnt=1,root,root_to,ban; boolvis[N],v1[N],v2[N]; voidins(intu,intv){ cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt; } voidfindcir(intu,intfa){ for(inti=head[u];i;i=e[i].next){ intv=e[i].to; if(!vis[v]){ vis[v]=true; findcir(v,u); }elseif(v!=fa)root=u,root_to=v,ban=i; } } voiddpcir(intu){ dp[u][0]=0;dp[u][1]=val[u]; for(inti=head[u];i;i=e[i].next) if(i!=ban&&(i^1)!=ban&&!v1[e[i].to]){ intv=e[i].to; v1[v]=true; dpcir(v); dp[u][0]+=max(dp[v][1],dp[v][0]); dp[u][1]+=dp[v][0]; } } voiddpban(intu){ dp[u][0]=0;dp[u][1]=val[u]; for(inti=head[u];i;i=e[i].next) if(i!=ban&&(i^1)!=ban&&!v2[e[i].to]){ intv=e[i].to; v2[v]=true; dpban(v); dp[u][1]+=dp[v][0]; if(v==root_to)dp[u][0]+=dp[v][0]; elsedp[u][0]+=max(dp[v][0],dp[v][1]); } } intmain(){ intn;scanf("%d",&n);intto; for(inti=1;i<=n;i++){ scanf("%lld%d",&val[i],&to); ins(i,to);ins(to,i); } ll ans=0,res; for(inti=1;i<=n;i++) if(!vis[i]){ vis[i]=true;findcir(i,0); v1[root]=true;dpcir(root);res=dp[root][0]; v2[root]=true;dpban(root);res=max(res,max(dp[root][0],dp[root][1])); ans+=res; } printf("%lld",ans); return0; }