视频链接:
// Luogu P2607 [ZJOI2008] 骑士 #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=1e6+10; typedef long long LL; int n; struct edge{int v,ne;}e[N]; int h[N],w[N],idx; int r1,r2,vis[N]; LL f[N][2],sum; void add(int a,int b){ e[++idx]={b,h[a]}; h[a]=idx; } void find(int u,int rt){//找两个根 vis[u]=1; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(v==rt){r1=u,r2=v;return;} if(vis[v])continue; find(v,rt); } } LL dfs(int u,int rt){//树上DP f[u][0]=0; f[u][1]=w[u]; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; 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]; } int main(){ scanf("%d",&n); for(int v=1,u;v<=n;v++){ scanf("%d%d",&w[v],&u); add(u,v);//单向边 } 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); } } } printf("%lld",sum); return 0; }
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e6+10;
int n;
struct edge{int v,ne;}e[N<<1];
int h[N],w[N],idx;
int fa[N]; //并查集的根数组
LL f[N][2],sum;
vector<PII> roots;
void add(int a,int b){
e[++idx]={b,h[a]};
h[a]=idx;
}
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
LL dfs(int u,int fa){//树上DP
f[u][0]=0; f[u][1]=w[u];
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
}
return f[u][0];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1,x;i<=n;i++){
scanf("%d%d",&w[i],&x);
int pa=find(i),pb=find(x);
if(pa!=pb){
fa[pa]=pb;//合并
add(i,x),add(x,i);//加边
}
else
roots.push_back({x,i});//存根
}
for(auto t:roots){
int a=t.first,b=t.second;
sum+=max(dfs(a,-1),dfs(b,-1));
}
printf("%lld",sum);
return 0;
}
原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/273490.html