题目:http://www.joyoi.cn/problem/tyvj-1940

基环树的样子,看了书上的讲解,准备写树上DP,然后挂了:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const MAXN=1e6+,inf=1e9;
int n,a[MAXN],f[MAXN][],head[MAXN],ct,s[MAXN],h,col[MAXN],cr,rt,ans;
int sta[MAXN],top,reg[MAXN];
bool in[MAXN],fl,vis[MAXN];
struct N{
int to,next;
N(int t=,int n=):to(t),next(n) {}
}edge[MAXN];
void add(int x,int y)
{
edge[++ct]=N(y,head[x]);head[x]=ct;
edge[++ct]=N(x,head[y]);head[y]=ct;
}
void ser(int x)
{
col[x]=cr;
for(int i=head[x],u;i;i=edge[i].next)
if(!col[u=edge[i].to])ser(u);
}
void tj(int rt,int x)
{
if(fl)return;
sta[++top]=x;vis[x]=;
for(int i=head[x],u;i;i=edge[i].next)
{
if(edge[i].to==a[x])continue;
if(!vis[u=edge[i].to])tj(rt,u);
else
{
while(sta[top]!=rt)
{
int t=sta[top];
s[++h]=t;
in[t]=;top--;
}
in[rt]=;s[++h]=rt;top--;
fl=;return;
}
}
top--;
}
void dfs(int x)
{
int mn=inf,sum=;
for(int i=head[x],u;i;i=edge[i].next)
{
u=edge[i].to;
if(u==rt)continue;
if(u==a[x]||col[u]!=col[x])continue;
dfs(u);
f[x][]+=max(f[u][],f[u][]);
sum+=f[u][];
mn=min(mn,f[u][]-f[u][]);
}
if(sum==)f[x][]=;
else f[x][]=sum-mn;
}
void dfs2(int x)
{
int mn=inf,sum=;
for(int i=head[x],u;i;i=edge[i].next)
{
u=edge[i].to;
if(u==rt)continue;
if(u==a[x]||col[u]!=col[x])continue;
dfs(u);
f[x][]+=max(f[u][],f[u][]);
sum+=f[u][];
mn=min(mn,f[u][]-f[u][]);
}
if(sum==)f[x][]=;
else if(x==a[rt])f[x][]=sum;
else f[x][]=sum-mn;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
reg[i]++;reg[a[i]]++;
add(i,a[i]);
}
for(int i=;i<=n;i++)
{
if(!col[i])h=,cr++,ser(i);
int rt;fl=;int s=;
for(int j=;j<=n;j++)
if(reg[j]>&&col[j]==cr)
{rt=j;break;}
tj(rt,i);
dfs(rt);
s=max(f[rt][],f[rt][]);
dfs2(rt);
s=max(s,f[rt][]);
ans+=s;
}
printf("%d",ans);
return ;
}

无输出的冗长树上DP

题目挺有意思,自己本来也想过贪心的做法,但不会处理链与环交接处的问题,想不清楚一条链会对环有什么影响;

然后看了看别人的博客,才发现链对环没有影响。。。因为环上的点不论链上怎样,仍还有环上别的点限制它;

所以链与环都是隔一个选一个,贪心。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>q;
int const MAXN=1e6+;
int n,a[MAXN],reg[MAXN],ans;
bool vis[MAXN],v2[MAXN];
void bfs()
{
for(int i=;i<=n;i++)
if(!reg[i])q.push(i);
while(q.size())
{
int x=q.front();q.pop();
vis[x]=;
if(!vis[a[x]])
{
ans++;//因为多起点开始,不方便直接求链的长度,所以一个一个加
vis[a[x]]=;
reg[a[a[x]]]--;
if(!reg[a[a[x]]]&&!vis[a[a[x]]])
q.push(a[a[x]]);
}
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
reg[a[i]]++;
}
bfs();
for(int i=;i<=n;i++)
if(!vis[i]&&!v2[i])
{
int cnt=;v2[i]=;
int j=a[i];
while(!v2[j])cnt++,j=a[j];
ans+=cnt/;
}
printf("%d",ans);
return ;
}

tyvj1940创世纪——贪心(基环树)的更多相关文章

  1. BZOJ3037 创世纪(基环树DP)

    基环树DP,攻的当受的儿子,f表选,g表不选.并查集维护攻受关系.若有环则记录,DP受的后把它当祖宗,再DP攻的. #include <cstdio> #include <iostr ...

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

    创世纪 SZP bzoj-3037/2068 Poi-2004 题目大意:给你n个物品,每个物品可以且仅可以控制一个物品.问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物 ...

  3. BZOJ3037 创世纪[基环树DP]

    实际上基环树DP的名字是假的.. 这个限制关系可以看成每个点有一条出边,所以就是一个内向基环树森林. 找出每个基环树的环,然后对于树的部分,做DP,设状态选或不选为$f_{x,0/1}$,则 $f_{ ...

  4. luogu3651 展翅翱翔之时 (はばたきのとき)[基环树+贪心]

    考前随便做点水题愉♂悦身心 有助于退役 这题意思其实就是说要把外向基环树森林改成一个环的最小代价. 依照套路,先对每棵基环树的树做dp,这里因为要是环,要把所有的树都拆成链,然后连接.所以考虑以最小代 ...

  5. Solution -「基环树」做题记录

    写的大多只是思路,比较简单的细节和证明过程就不放了,有需者自取. 基环树简介 简单说一说基环树吧.由名字扩展可得这是一类以环为基础的树(当然显然它不是树. 通常的表现形式是一棵树再加一条非树边,把图画 ...

  6. Poetize4 创世纪

    3037: 创世纪 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 123  Solved: 66[Submit][Status] Description ...

  7. 【BZOJ3037/2068】创世纪/[Poi2004]SZP 树形DP

    [BZOJ3037]创世纪 Description applepi手里有一本书<创世纪>,里面记录了这样一个故事……上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放 ...

  8. JZOJ 3929. 【NOIP2014模拟11.6】创世纪

    3929. [NOIP2014模拟11.6]创世纪 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Description 上帝手 ...

  9. 与图论的邂逅01:树的直径&基环树&单调队列

    树的直径 定义:树中最远的两个节点之间的距离被称为树的直径.  怎么求呢?有两种官方的算法(不要问官方指谁我也不晓得): 1.两次搜索.首先任选一个点,从它开始搜索,找到离它最远的节点x.然后从x开始 ...

随机推荐

  1. 从SDCard获取的图片按分辨率处理的方法

    前段时间公司开发的Launcher要做主题切换的功能,但切换主题时须要从sdcard中获取要切换的图片资源,拿到后图片的大小不正常. 后来查找原因是:系统对不同分辨率拿到的图片资源会自己主动的做转化, ...

  2. iOS 多线程技术2

    iOS 多线程技术2 NSOperation NSInvocationOperation //创建一个队列 NSOperationQueue *queue = [[NSOperationQueue a ...

  3. urllib(最基本的)库的应用

    Urllib库 python内置的http请求库 1.urllib.request 请求模块 2.urllib.error 异常处理模块(try,catch) 3.urllib.parse url解析 ...

  4. css3 - target

    通过CSS3伪元素target,我们可以实现拉风琴 源码 <!DOCTYPE HTML> <html lang="en-US"> <head> ...

  5. Eclipse 修改字符集

    Eclipse 修改字符集 默认情况下 Eclipse 字符集为 GBK,但现在很多项目采用的是 UTF-8,这是我们就需要设置我们的 Eclipse 开发环境字符集为 UTF-8, 设置步骤如下: ...

  6. DM8168 unrecoverable error: OMX_ErrorBadParameter (0x80001005) [resolved]

    DM8168 custom board 成功启动系统之后想先測一下8168编解码功能,把开发包里的examples跑一遍.启动完毕后.连上HDMI显示,在starting Matrix GUI app ...

  7. HDU 4923 Room and Moor(推理+栈维护)

    HDU 4924 Room and Moor 题目链接 题意:给定一个01组成的a序列.要求一个b序列,b序列每一个数值为[0, 1]之间的数,而且b序列为非递减序列,要求∑(ai−bi)2最小,求这 ...

  8. nodejs websocket 聊天应用

    前端一直是一块充满惊喜的土地,不仅是那些富有创造性的页面,还有那些惊赞的效果及不断推出的新技术.像node.js这样的后端开拓者直接将前端人员的能力扩大到了后端.瞬间就有了一统天下的感觉,来往穿梭于前 ...

  9. vim 插件: ctrlp.vim

    vim-scripts 里可以搜到这个插件. 安装好了之后,在 vim 的 normal 模式之下按 Ctrl+P 组合键即可弹出搜索窗口. * <f5> 更新目录缓存. * <c- ...

  10. HashSet、LinkHashSet、TreeSet总结

    HashSet:散列集,集合中的元素不允许重复,但是不要求顺序,输出的顺序和进入HashSet的顺序是没有关系的 LinkedHashSet :链表散列集,集合中的元素不允许重复,同时要求和进入Set ...