仙人掌暂时不会,只好来水一水基环外向树。
话说无向的到底应该怎么叫?外向?内向?基环无向树(太诡异了)?
然后对于这道题,由于是基环,所以要拆掉环上的一条边(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;
}