题目(bzoj)
这题一看就是个dp......O(n)的树形dp。
然后这就是个基环树dp,基环树dp的套路就是:断环成树,树形dp
所以就这么整吧!
dp[u][0]表示u这个点不选时的最大值,dp[u][1]表示选这个点时的最大值。
状态转移很好写,
dp[u][0]=∑max(dp[v][0],dp[v][1]),
dp[u][1]=∑dp[v][0],
初始值为dp[u][0]=0,dp[u][1]=a[u]。
设每次断的边的两个端点为x1,x2,并且强制这个点不能选,
那么ans就加上max(dp[x1][0],dp[x2][0]);
如果没有断环,就直接ans加上dp[i][0],
完毕。
另外注意一下重边的情况:也很简单,弄个时间戳标记一下即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <climits>
#define ll long long
#define llmax LONG_LONG_MAX
#define llmin LONG_LONG_MIN
#define readf(f) scanf("%lf",&f)
using namespace std;
template <class _E> inline void read(_E &e)
{
e=0;bool ck=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')ck=1;ch=getchar();}
while(ch>='0'&&ch<='9'){e=e*10+ch-'0';ch=getchar();}
if(ck)e=-e;
}
int dfn[1000005],idx;
int n;
ll a[1000005];
ll dp[1000005][2];
int vis[1000005];
bool flag;
struct edge{
int vk;
int nxt;
bool exist;
}e[2000005];
int t,head[1000005];
inline void ad(int u,int v)
{
e[++t].vk=v;
e[t].nxt=head[u];
e[t].exist=true;
head[u]=t;
}
int x1,x2;
void dfs_huan(int u,int fa)
{
++vis[u];
for (int i=head[u];i;i=e[i].nxt)
{
int v=e[i].vk;
if (v==fa) continue;
if (vis[v]==1 && !flag)
{
x1=u,x2=v;
flag=true;
}
else if (!vis[v])
dfs_huan(v,u);
}
++vis[u];
}
void dfs_dp(int u,int fa)
{
dfn[u]=idx;
dp[u][0]=0,dp[u][1]=a[u];
for (int i=head[u];i;i=e[i].nxt)
{
int v=e[i].vk;
if (v==fa || !e[i].exist || dfn[v]>=idx) continue;
dfs_dp(v,u);
dp[u][0]+=max(dp[v][0],dp[v][1]);
dp[u][1]+=dp[v][0];
}
}
ll ans;
int main()
{
read(n);
for (int i=1;i<=n;++i)
{
int vv;
read(a[i]),read(vv);
ad(i,vv),ad(vv,i);
}
for (int i=1;i<=n;++i)
{
if (!vis[i])
{
flag=false;
ll tmp;
dfs_huan(i,0);
if (flag)
{
for (int k=head[x1];k;k=e[k].nxt)
if (e[k].vk==x2) e[k].exist=false;
for (int k=head[x2];k;k=e[k].nxt)
if (e[k].vk==x1) e[k].exist=false;
++idx;dfs_dp(x1,0);
tmp=dp[x1][0];
++idx;dfs_dp(x2,0);
tmp=max(tmp,dp[x2][0]);
ans+=tmp;
}
else
{
++idx;dfs_dp(i,0);
ans+=max(dp[i][0],dp[i][1]);
}
}
}
printf("%lld",ans);
return 0;
}






Comments NOTHING