您的位置:首页 > 其它

1040: [ZJOI2008]骑士

2015-12-22 19:00 218 查看
仙人掌暂时不会,只好来水一水基环外向树。

话说无向的到底应该怎么叫?外向?内向?基环无向树(太诡异了)?

然后对于这道题,由于是基环,所以要拆掉环上的一条边(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
[2],val
;
inthead
,cnt=1,root,root_to,ban;
boolvis
,v1
,v2
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: