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

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

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. int const MAXN=1e6+,inf=1e9;
  6. int n,a[MAXN],f[MAXN][],head[MAXN],ct,s[MAXN],h,col[MAXN],cr,rt,ans;
  7. int sta[MAXN],top,reg[MAXN];
  8. bool in[MAXN],fl,vis[MAXN];
  9. struct N{
  10. int to,next;
  11. N(int t=,int n=):to(t),next(n) {}
  12. }edge[MAXN];
  13. void add(int x,int y)
  14. {
  15. edge[++ct]=N(y,head[x]);head[x]=ct;
  16. edge[++ct]=N(x,head[y]);head[y]=ct;
  17. }
  18. void ser(int x)
  19. {
  20. col[x]=cr;
  21. for(int i=head[x],u;i;i=edge[i].next)
  22. if(!col[u=edge[i].to])ser(u);
  23. }
  24. void tj(int rt,int x)
  25. {
  26. if(fl)return;
  27. sta[++top]=x;vis[x]=;
  28. for(int i=head[x],u;i;i=edge[i].next)
  29. {
  30. if(edge[i].to==a[x])continue;
  31. if(!vis[u=edge[i].to])tj(rt,u);
  32. else
  33. {
  34. while(sta[top]!=rt)
  35. {
  36. int t=sta[top];
  37. s[++h]=t;
  38. in[t]=;top--;
  39. }
  40. in[rt]=;s[++h]=rt;top--;
  41. fl=;return;
  42. }
  43. }
  44. top--;
  45. }
  46. void dfs(int x)
  47. {
  48. int mn=inf,sum=;
  49. for(int i=head[x],u;i;i=edge[i].next)
  50. {
  51. u=edge[i].to;
  52. if(u==rt)continue;
  53. if(u==a[x]||col[u]!=col[x])continue;
  54. dfs(u);
  55. f[x][]+=max(f[u][],f[u][]);
  56. sum+=f[u][];
  57. mn=min(mn,f[u][]-f[u][]);
  58. }
  59. if(sum==)f[x][]=;
  60. else f[x][]=sum-mn;
  61. }
  62. void dfs2(int x)
  63. {
  64. int mn=inf,sum=;
  65. for(int i=head[x],u;i;i=edge[i].next)
  66. {
  67. u=edge[i].to;
  68. if(u==rt)continue;
  69. if(u==a[x]||col[u]!=col[x])continue;
  70. dfs(u);
  71. f[x][]+=max(f[u][],f[u][]);
  72. sum+=f[u][];
  73. mn=min(mn,f[u][]-f[u][]);
  74. }
  75. if(sum==)f[x][]=;
  76. else if(x==a[rt])f[x][]=sum;
  77. else f[x][]=sum-mn;
  78. }
  79. int main()
  80. {
  81. scanf("%d",&n);
  82. for(int i=;i<=n;i++)
  83. {
  84. scanf("%d",&a[i]);
  85. reg[i]++;reg[a[i]]++;
  86. add(i,a[i]);
  87. }
  88. for(int i=;i<=n;i++)
  89. {
  90. if(!col[i])h=,cr++,ser(i);
  91. int rt;fl=;int s=;
  92. for(int j=;j<=n;j++)
  93. if(reg[j]>&&col[j]==cr)
  94. {rt=j;break;}
  95. tj(rt,i);
  96. dfs(rt);
  97. s=max(f[rt][],f[rt][]);
  98. dfs2(rt);
  99. s=max(s,f[rt][]);
  100. ans+=s;
  101. }
  102. printf("%d",ans);
  103. return ;
  104. }

无输出的冗长树上DP

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

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

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

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<queue>
  5. using namespace std;
  6. queue<int>q;
  7. int const MAXN=1e6+;
  8. int n,a[MAXN],reg[MAXN],ans;
  9. bool vis[MAXN],v2[MAXN];
  10. void bfs()
  11. {
  12. for(int i=;i<=n;i++)
  13. if(!reg[i])q.push(i);
  14. while(q.size())
  15. {
  16. int x=q.front();q.pop();
  17. vis[x]=;
  18. if(!vis[a[x]])
  19. {
  20. ans++;//因为多起点开始,不方便直接求链的长度,所以一个一个加
  21. vis[a[x]]=;
  22. reg[a[a[x]]]--;
  23. if(!reg[a[a[x]]]&&!vis[a[a[x]]])
  24. q.push(a[a[x]]);
  25. }
  26. }
  27. }
  28. int main()
  29. {
  30. scanf("%d",&n);
  31. for(int i=;i<=n;i++)
  32. {
  33. scanf("%d",&a[i]);
  34. reg[a[i]]++;
  35. }
  36. bfs();
  37. for(int i=;i<=n;i++)
  38. if(!vis[i]&&!v2[i])
  39. {
  40. int cnt=;v2[i]=;
  41. int j=a[i];
  42. while(!v2[j])cnt++,j=a[j];
  43. ans+=cnt/;
  44. }
  45. printf("%d",ans);
  46. return ;
  47. }

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. Jquery:怎样让子窗体的div显示在父窗体之上

    <1> js或者jQuery訪问页面中的框架iframe.  注意:框架内的页面是不能跨域的! 如果有两个页面,在同样域下. 如果:父窗体  index.html ,有id 为 subif ...

  2. ios 清理缓存(EGO)

    一段清理缓存的代码例如以下: dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,) , ^{ NSSt ...

  3. java多个文件压缩下载

    public static void zipFiles(File[] srcfile,ServletOutputStream sos){ byte[] buf=new byte[1024]; try ...

  4. python(36)- 测试题

    1.8<<2等于? 32 “<<”位运算 264 132 64 32 16 8 4 2 1 原始位置 0 0 0 0 0 1 0 0 0 想左位移2位 0 0 0 1 0 0 ...

  5. Laravel建站04--建立后台文章管理

    路由配置 Route::group(['middleware' => 'auth', 'namespace' => 'Admin', 'prefix' => 'admin'], fu ...

  6. kubectl技巧之通过jsonpath截取属性

    系列目录 前面一节我们介绍了使用go-template截取属性,go-template功能非常强大,可以定义变量,使用流程控制等,这是jsonpath所不具备的.然而,jsonpth使用的时候更为灵活 ...

  7. Machine Learning: 一部气势恢宏的人工智能发展史

    转载自:雷锋网 本文作者:陈圳 2016-09-12 09:46 导语:机器学习的从产生,发展,低潮和全盛的历史 雷锋网(公众号:雷锋网)按:本文作者DataCastle数据城堡,主要介绍了机器学习的 ...

  8. 改动UITextfield的Placeholder字体的颜色

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  9. 【机器学习算法-python实现】PCA 主成分分析、降维

    1.背景         PCA(Principal Component Analysis),PAC的作用主要是减少数据集的维度,然后挑选出基本的特征.         PCA的主要思想是移动坐标轴, ...

  10. JavaScript中批量设置Css样式

    设置 input 元素的  属性: document.getElementsByTagName("INPUT")[0].setAttribute("属性",&q ...