BZOJ 3037 创世纪

题解:

首先从基环树上的环上选两个点x,y

断开x,y之间的边,然后做树形DP.

设f[x]为选x的情况下的最大值,g[x]为不选x的情况下的最大值.

分两种情况讨论,

1.选x,则y一开始就处于被支配状态,在计算y的f[]函数值时需要特判.

2.不选x,按正常DP做即可.

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 #define ll long long
 5 #define FILE "dealing"
 6 #define up(i,j,n) for(int i=j;i<=n;i++)
 7 #define db long double
 8 #define pii pair<int,int>
 9 #define pb push_back
10 #define mem(a,L) memset(a,0,sizeof(int)*(L+1))
11 template<class T> inline bool cmin(T& a,T b){return a>b?a=b,true:false;}
12 template<class T> inline bool cmax(T& a,T b){return a<b?a=b,true:false;}
13 template<class T> inline T squ(T a){return a*a;}
14 const ll maxn=2000100+10,inf=1e9+10,limit=1e7;
15 int read(){
16     int x=0,f=1,ch=getchar();
17     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
18     while(ch>=‘0‘&&ch<=‘9‘)x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar();
19     return x*f;
20 }
21 int n;
22 vector<int> t[maxn];
23 int f[maxn],g[maxn],to[maxn];
24 int vis[maxn];
25 int rt,rt2,q[maxn],top=0;
26 void dfs(int x){
27     q[++top]=x;
28     vis[x]=1;
29     if(!vis[to[x]])dfs(to[x]);
30     else {
31         rt=x;
32         rt2=to[x];
33     }
34 }
35 void dfs2(int x){
36     vis[x]=1;
37     for(int i=0;i<t[x].size();i++)
38         if(!vis[t[x][i]])dfs2(t[x][i]);
39     if(!vis[to[x]])dfs2(to[x]);
40 }
41 //f[x] 选 g[x] 不选
42 int flag=0;
43 void dfs1(int x){//选rt
44     f[x]=1,g[x]=0;int Max=-inf;
45     for(int i=0;i<t[x].size();i++){
46         int y=t[x][i];if((x==rt2&&y==rt))continue;
47         dfs1(y);
48         f[x]+=f[y];
49         g[x]+=f[y];
50         cmax(Max,g[y]-f[y]);
51     }
52     f[x]+=Max;
53     if(x==rt2&&flag)f[x]-=Max;
54     cmax(f[x],0);
55 }
56
57 int main(){
58     freopen(FILE".in","r",stdin);
59     freopen(FILE".out","w",stdout);
60     n=read();
61     up(i,1,n){
62         to[i]=read();
63         t[to[i]].push_back(i);
64     }
65     int ans=0;
66     up(i,1,n){
67         if(vis[i])continue;
68         top=0;dfs(i);
69         while(top)vis[q[top--]]=0;
70         dfs2(i);
71         int Ans=0;
72         flag=1;
73         dfs1(rt);
74         cmax(Ans,g[rt]);
75         flag=0;
76         dfs1(rt);
77         cmax(Ans,f[rt]);
78         ans+=Ans;
79     }
80     printf("%d\n",ans);
81     return 0;
82 }

时间: 2024-07-28 19:49:36

BZOJ 3037 创世纪的相关文章

BZOJ 3037 创世纪 树形DP

题目大意:给定一张有向图,每个点有且仅有一条出边,要求若一个点x扔下去,至少存在一个保留的点y,y的出边指向x,求最多扔下去多少个点 首先原题的意思就是支配关系 我们反向考虑 求最少保留的点 要求一个点若扔出去 则必须存在一个保留的点指向它 于是这就是最小支配集 不过由于是有向图 所以一个点要么选择 要么被子节点支配 所以就只剩下2个状态了 设f[x]为以x为根的子树选择x的最小支配集 g[x]为不选择x的最小支配集 然后由于是基环树林 所以我们选择一个环上的点 拆掉它的出边 设这个点为x 出边

Android创世纪

1. 创建第一个Android应用程序 2. Android应用程序目录结构 3. 运行Android应用程序 1. 创建第一个Android应用程序 New--->Android Project   各参数意义在蓝色问号处点击即可查看 后面的基本是默认, 了解每一页是做什么的即可 src                                                      包--->源文件 gen Generated Java Files                 

bzoj3037: 创世纪

Description applepi手里有一本书<创世纪>,里面记录了这样一个故事……上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放到一个新的空间中去以建造世界.每种世界元素都可以限制另外一种世界元素,所以说上帝希望所有被投放的世界元素都有至少一个没有被投放的世界元素能够限制它,这样上帝就可以保持对世界的控制.由于那个著名的有关于上帝能不能制造一块连自己都不能举起的大石头的二律背反命题,我们知道上帝不是万能的,而且不但不是万能的,他甚至有事情需要找你帮忙——上帝希望

codevs1919创世纪

1919 创世纪 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 上帝手中有着N 种被称作"世界元素"的东西,现在他要把它们中的一部分投放到一个新的空间中去以建造世界.每种世界元素都可以限制另外一种世界元素,所以说上帝希望所有被投放的世界元素都有至少一个没有被投放的世界元素能够限制它,这样上帝就可以保持对世界的控制.由于那个著名的有关于上帝能不能制造一块连自己都不能举起的大石头的二律背反命题,我们知道上帝不是万能的

[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树

创世纪 SZP bzoj-3037/2068 Poi-2004 题目大意:给你n个物品,每个物品可以且仅可以控制一个物品.问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物品,而且选取的个数最大. 注释:$1\le n \le 10^6$. 想法:显然,和骑士类似的,是一个基环树森林.如果A物品可以控制B物品,那就有B物品向A物品连边.对于每一个基环树,如果这个基环树是树的话显然变成树形dp入门题,暴力树形dp即可.然后对于基环树来讲,我们依然记录环上两点,分别以这两

创世纪互助之王模式解析,三九软件互助系统开发

制度介绍[注册流程]1.向推荐人购买激活币和排单币,由推荐人登录平台以"点击激活会员"的形式完成注册,注册一个账户需要扣除推荐人1个激活币,激活币100一个.(激活后需要完善资料,姓名,×××号,银行卡号,交易密码)2.用户登录ID默认为手机号,手机号不能重复,所以一个手机号和一个×××只能注册一个账户.杜绝多账号,系统会不定期检测,一经发现过多账号,有权冻结其账户,注册成功后,平台自动发送短信将登录用户名与默认密码发送给新会员[静态收益]1.排单规则:每七天可排单一次,每次排单金额必

创世纪互助之王模式解析,互助系统开发

[注册流程]1.向推荐人购买激活币和排单币,由推荐人登录平台以"点击激活会员"的形式完成注册,注册一个账户需要扣除推荐人1个激活币,激活币100一个.(激活后需要完善资料,姓名,身 份 证 号,银行卡号,交易密码)2.用户登录ID默认为手机号,手机号不能重复,所以一个手机号和一个身 份 证只能注册一个账户.杜绝多账号,系统会不定期检测,一经发现过多账号,有权冻结其账户,注册成功后,平台自动发送短信将登录用户名与默认密码发送给新会员[静态收益]1.排单规则:每七天可排单一次,每次排单金额

创世纪游戏、黄金分割比

创世纪游戏 N个人,参与M轮法案的投票.每个人可以提出任意的法案,提出的法案会放到法案队列中,对于每条法案,每个人有4中决策:一票通过.通过.否决.一票否决.一票通过和一票否决会抵消.通过和否决会抵消.一票否决大于一票通过,一票通过大于否决. 如果法案顺利通过,则执行法案中的条款. 更复杂一些: def main(): rule_q=[] now_state=[[]] while rule_q is not empty: x=rule_q.pop() res=judge(x) if pass(r

MFC建立应用程序启示录(创世纪新篇)

MFC是vc+的核心部分,需要一定的编程功底. Windows编程基础 编制一个功能强大和易操作的Windows应用程序所需要的代码肯定会比一般的C++程序要多得多,但并不是所有的代码都需要自己从头开始编写,因为Visual C++不仅提供了常用的Windows应用程序的基本框架,而且可以在框架程序中直接调用Win32 API(Application Programming Interface, 应用程序接口)函数.这样,用户仅需要在相应的框架位置中添加自己的代码或修改部分代码就可实现Windo