首页 > 其他分享 >P10933 创世纪 题解

P10933 创世纪 题解

时间:2024-08-24 21:05:12浏览次数:4  
标签:2000010 minn int 题解 P10933 cnt dfs max 创世纪

题目传送门

前置知识

树形 DP

解法

将 \(a_{i}\) 向 \(i\) 连一条有向边,这样就形成了基环外向树森林。

设 \(f_{x,0/1}\) 表示 \(x\) 不选/选时,以 \(x\) 为根的子树的最多选择个数,状态转移方程为 \(\begin{cases} f_{x,0}=\sum\limits_{y \in Son(x)} \max(f_{y,0},f_{y,1}) \\ f_{x,1}=1+\max\limits_{y \in Son(x)} \{ f_{y,0}+\sum\limits_{z \in Son(x),z \ne y} \max(f_{z,0},f_{z,1}) \}=1+f_{x,0}- \min\limits_{y \in Son(x)} \{ \max(f_{y,0},f_{y,1})-f_{y,0} \} \end{cases}\)。

最后处理下环形 DP 的取或不取即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
struct node
{
    int nxt,to;
}e[2000010];
int head[2000010],vis[2000010],u[2000010],v[2000010],f[2000010][2],rt,cnt=0;
void add(int u,int v)
{
    cnt++;
    e[cnt].nxt=head[u];
    e[cnt].to=v;
    head[u]=cnt;
}
int dfs_huan(int x)
{
    vis[x]=1;
    return (vis[u[x]]==1)?x:dfs_huan(u[x]);
}
void dfs(int x)
{
    int minn=0x3f3f3f3f;
    vis[x]=1;
    f[x][0]=0;
    for(int i=head[x];i!=0;i=e[i].nxt)
    {
        if(e[i].to==rt)
        {
            f[e[i].to][1]=-0x3f3f3f3f;
        }
        else
        {
            dfs(e[i].to);
            f[x][0]+=max(f[e[i].to][0],f[e[i].to][1]);
            minn=min(minn,max(f[e[i].to][0],f[e[i].to][1])-f[e[i].to][0]);
        }
    }
    f[x][1]=1+f[x][0]-minn;
}
int main()
{
    int n,ans=0,maxx,i;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        v[i]=i;
        cin>>u[i];
        add(u[i],v[i]);
    }
    for(i=1;i<=n;i++)
    {
        if(vis[i]==0)
        {
            rt=dfs_huan(i);
            dfs(rt);
            maxx=max(f[rt][0],f[rt][1]);
            rt=u[rt];
            dfs(rt);
            ans+=max(maxx,f[rt][1]);
        }
    }
    cout<<ans<<endl;
    return 0;
}

标签:2000010,minn,int,题解,P10933,cnt,dfs,max,创世纪
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18378257

相关文章

  • P10957 环路运输 题解
    题目传送门前置知识单调队列/单调栈优化解法在仓库\(1\)和\(n\)之间把环断开,然后复制一倍接在末尾,形成长度为\(2n\)的直线公路,即有\(a_{i}=a_{i+n}(1\lei\len)\)。对于原来环形公路上的任意两座仓库\(i,j(1\lej<i\len)\),代价为\(\begin{cases}a_{i}+a_{j}......
  • Chain Contestant 题解
    前言题目链接:洛谷;AtCoder。最慢的点才跑\(2\)ms的题解确定不看一看?题意简述给定长度为\(n\)的字符串\(s\),其中\(s_i\in\Omega\),求有多少子序列\(T\)满足任意\(x\in\Omega\),其在\(T\)出现的位置为连续一段,当然,对\(998244353\)取模。\(n\leq10^5\),\(|\Omeg......
  • P3547 [POI2013] CEN-Price List 题解
    Description给定一个\(n\)个点\(m\)条边的无向图,边权均为\(a\)。现在将原来图中满足最短路等于\(2a\)所有的点对\((x,y)\)之间加一条长度为\(b\)的无向边。给定\(k\),求点\(k\)到所有点的最短路是多少。\(1\leqn,m\leq10^5\)。Solution首先有个显然的结论是......
  • 洛谷P2440 木材加工 题解
    这是我找到的一篇很久之前为了让我更好理解二分写的详细题解题目链接code:#include<bits/stdc++.h>#defineintlonglong#defineMAXN0x3f3f3f3f3f3f3f3f#defineMINN-0x3f3f3f3f3f3f3f3f#defineMiraiios::sync_with_stdio(0),cin.tie(0),cout.tie(0);usingnamespa......
  • CF939F Cutlet题解
    前置单调队列(没学过或忘了点这里)简化题意有一块牛排,要求对它烹饪\(2n\)秒,可在给定的\(k\)个时间段中将它翻转任意次,使得牛排两面都受到了\(n\)秒的烹饪。状态设计可以发现当总共煮了\(i\)秒,其中一面如果煮了\(j\)秒,自然可以求出另一面为\(i-j\)秒,所以我们可以......
  • CSP 2023 提高级第一轮 CSP-S 2023初试题 程序阅读第三题解析
    一、程序阅读#include<vector>#include<algorithm>#include<iostream>usingnamespacestd;boolf0(vector<int>&a,intm,intk){ints=0;for(inti=0,j=0;i<a.size();i++){while(a[i]-a[j]>......
  • P10690 Fotile 模拟赛 L 题解
    题目传送门前置知识可持久化字典树|分块思想解法考虑分块预处理整块的答案,散块直接暴力。设\(f_{i,j}\)表示以\(i\)所在的块的左端点为左端点,\(j\)为右端点的最大异或和,可持久化01-Trie维护即可。本题中这种写法比处理整块到整块的答案更容易处理些。整块的答案......
  • 讨论TableLayoutPanel加载缓慢和闪烁问题解决方案
    WinForm加载多个自定义控件时,会出现很严重的闪烁问题,很卡,一块一块的加载(像打开网页时,网络很卡的那种感觉)简直没法忍受。在网上搜索了好久,网上大部分的方法是一下4种,但是都不能有效的解决问题。1、将DoubleBuffered设置true,用双缓存处理Form界面内容加载,可以提高页面显......
  • AtCoder Beginner Contest 367 A ~ F(无D题)题解
    AtCoderBeginnerContest367A~F(̸\notD)几天前就已经vp过了,但是忘写题解了今天才想起来痛,早知道这么简单,我就不在家里摆烂了A.ShoutEveryday罚了好几发,我打比......
  • CF1326F2 Wise Men (Hard Version) 题解
    题目链接点击打开链接题目解法挺难的。可能一步一步推下来也没那么复杂(?基本copytzc_wk的题解/bx肯定不能像\(F1\)用普通的状压求,一个技巧是容斥考虑令\(f_S\)表示\(S\)中为\(1\)的位置\(p_i\)和\(p_{i+1}\)必须认识,为\(0\)的位置随便\(f\)数组相当于答案......