骑士(基环树板子)
题目链接:https://www.luogu.com.cn/problem/P2607
题意:
略
思路:
图为外向树,(n个节点,n个边)
对于每一个连通块,先找环(每个连通块都有一个环)然后断环成树,跑树形dp板子
vector<int>e[maxn];
int vis[maxn],w[maxn];
ll f[maxn][2];
int r1,r2;
void find(int u,int rt){//找环
vis[u]=1;
for(int v:e[u]){
if(v==rt){
r1=u,r2=v;return;
}//找到环且遍历完连通块
if(vis[v])continue;
find(v,rt);
}
}
ll dfs(int u,int rt){
f[u][0]=0;f[u][1]=w[u];
for(int v:e[u]){
if(v==rt)continue;//断环操作,防止无限循环
dfs(v,rt);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
}
return f[u][0];//不选u
}
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++){
int v,u;cin>>v>>u;
e[u].pb(i);w[i]=v;
//让讨厌的骑士作为该骑士的父亲
}
int sum=0;
for(int i=1;i<=n;i++){
if(!vis[i]){//对于每一个连通块
r1=r2=0;
find(i,i);
if(r1){
ll res1=dfs(r1,r1);
ll res2=dfs(r2,r2);
sum+=max(res1,res2);
}
}
}
cout<<sum<<endl;
}

浙公网安备 33010602011771号