[CSAcademy]Cycle Tree

题目大意:

定义环树是一张无向连通的简单图,它的生成方式如下:

  1. \(2\)个点\(1\)条边的图是环树;
  2. 对任意一个环树,加入\(k\)个点\(a_{1\sim k}\),加入方式为从原图中选择一条边\((u,v)\),连接\((u,a_1),(a_1,a_2)\ldots(a_{k-1},a_k),(a_k,v)\),得到的图也是环树。

给定一个\(n(n\le5\times10^4)\)个点,\(m(m\le10^5)\)条边的环树,求最大独立集大小。

思路:

每次选取一个度数为\(2\)的点,将这条边删掉,将相邻的两点间连上虚点。不断进行这样的操作,最后只会剩下\(2\)个点。

\(f[0/1][0/1][i][j]\)表示对于边\((i,j)\),是否选取\(i/j\)的最大独立集,按照删点的顺序进行DP即可。

每个点最多被删一次,因此时间复杂度\(\mathcal O(n+m)\)。

源代码:

  1. #include<map>
  2. #include<set>
  3. #include<queue>
  4. #include<cstdio>
  5. #include<cctype>
  6. #include<climits>
  7. inline int getint() {
  8. register char ch;
  9. while(!isdigit(ch=getchar()));
  10. register int x=ch^'0';
  11. while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
  12. return x;
  13. }
  14. const int N=5e4+1;
  15. bool inq[N];
  16. std::queue<int> q;
  17. std::set<int> e[N],set[N];
  18. std::map<int,int> f[2][2][N];
  19. inline void add_edge(const int &u,const int &v) {
  20. e[u].emplace(v);
  21. e[v].emplace(u);
  22. }
  23. inline void add(int &x,const int &y) {
  24. x+=y;
  25. }
  26. inline void up(int &x,const int &y) {
  27. x=std::max(x,y);
  28. }
  29. int main() {
  30. const int n=getint(),m=getint();
  31. for(register int i=0;i<m;i++) {
  32. const int u=getint(),v=getint();
  33. add_edge(u,v);
  34. f[0][0][u][v]=f[0][0][v][u]=0;
  35. f[0][1][u][v]=f[1][0][v][u]=1;
  36. f[1][0][u][v]=f[0][1][v][u]=1;
  37. f[1][1][u][v]=f[1][1][v][u]=INT_MIN;
  38. set[u].insert(v);
  39. set[v].insert(u);
  40. }
  41. int ans=1;
  42. for(register int i=1;i<=n;i++) {
  43. if(e[i].size()==2) {
  44. q.push(i);
  45. inq[i]=true;
  46. }
  47. }
  48. while(!q.empty()) {
  49. const int x=q.front();
  50. q.pop();
  51. if(e[x].size()!=2) continue;
  52. const int u=*e[x].begin(),v=*e[x].rbegin();
  53. add(f[0][0][u][v],std::max(f[0][0][x][u]+f[0][0][x][v],f[1][0][x][u]+f[1][0][x][v]-1));
  54. add(f[0][1][u][v],std::max(f[0][0][x][u]+f[0][1][x][v],f[1][0][x][u]+f[1][1][x][v]-1)-!!f[0][1][u][v]);
  55. add(f[1][0][u][v],std::max(f[0][1][x][u]+f[0][0][x][v],f[1][1][x][u]+f[1][0][x][v]-1)-!!f[1][0][u][v]);
  56. if(!set[u].count(v)) add(f[1][1][u][v],std::max(f[0][1][x][u]+f[0][1][x][v],f[1][1][x][u]+f[1][1][x][v]-1)-2*!!f[1][1][u][v]);
  57. up(ans,f[0][0][v][u]=f[0][0][u][v]);
  58. up(ans,f[1][0][v][u]=f[0][1][u][v]);
  59. up(ans,f[0][1][v][u]=f[1][0][u][v]);
  60. up(ans,f[1][1][v][u]=f[1][1][u][v]);
  61. e[x].clear();
  62. e[u].erase(x);
  63. e[v].erase(x);
  64. e[u].insert(v);
  65. e[v].insert(u);
  66. if(e[u].size()==2&&!inq[u]) {
  67. q.push(u);
  68. inq[u]=true;
  69. }
  70. if(e[v].size()==2&&!inq[v]) {
  71. q.push(v);
  72. inq[v]=true;
  73. }
  74. }
  75. printf("%d\n",ans);
  76. return 0;
  77. }

[CSAcademy]Cycle Tree的更多相关文章

  1. [CSAcademy]Connected Tree Subgraphs

    题目大意: 给你一棵n个结点的树,求有多少种染色方案,使得染色过程中染过色的结点始终连成一块. 思路: 树形DP. 设f[x]表示先放x时,x的子树中的染色方案数,y为x的子结点. 则f[x]=pro ...

  2. 4105: [Thu Summer Camp 2015]平方运算

    首先嘛这道题目只要知道一个东西就很容易了:所有循环的最小公约数<=60,成一条链的长度最大为11,那么我们就可以用一个很裸的方法.对于在链上的数,我们修改直接暴力找出并修改.对于在环上的数,我们 ...

  3. Leetcode: Graph Valid Tree && Summary: Detect cycle in undirected graph

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  4. [CSAcademy]Find the Tree

    [CSAcademy]Find the Tree 题目大意: 交互题. 有一棵\(n(n\le2000)\)个结点的树,但是你并不知道树的形态.你可以调用\({\rm query}(x,y,z)\)( ...

  5. [CSAcademy]Virus on a Tree

    [CSAcademy]Virus on a Tree 题目大意: 给你一棵\(n(n\le10^5)\)个点的树,一开始点\(1\)有病毒,可以沿着边扩散.你可以事先切掉若干条边,使得病毒扩散不超过\ ...

  6. Terminating app due to uncaught exception 'CALayerInvalid', reason: 'layer <CALayer: 0x7fda42c66e30> is a part of cycle in its layer tree'

    iOS App里面所有的View构成一个组件树,这个树里面如果有了闭环就会出现这个报错,最常见的你不小在某UIViewController里面写了这样的代码: someView.addSubView( ...

  7. [LeetCode] Convert Sorted List to Binary Search Tree 将有序链表转为二叉搜索树

    Given a singly linked list where elements are sorted in ascending order, convert it to a height bala ...

  8. 学习RxJS:Cycle.js

    原文地址:http://www.moye.me/2016/06/16/learning_rxjs_part_two_cycle-js/ 是什么 Cycle.js 是一个极简的JavaScript框架( ...

  9. Graph Valid Tree

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

随机推荐

  1. Jenkins远程调度Shell命令

    http://blog.csdn.net/fireofjava/article/details/40624353 Jenkins服务器为Win7版本,需要远程调用CentOS服务器上Shell脚本,然 ...

  2. 我所知道的MVVM框架(转 司徒大大 )

    RubyLouvre commented on 6 Sep 2014   avalon http://avalonjs.github.io/ (使用Object.defineProperties. V ...

  3. poj1095

    题意:给出n,要求输出第n个二叉树,二叉树编号规则如下图所示: 分析:g[i]表示有i个节点的二叉树,有多少种.f[i][j]表示有i个节点,且左子树有j个节点的树有多少种. sumg[i]表示g数组 ...

  4. python logging 日志

    logging与print 区别,为什么需要logging? 在写脚本的过程中,为了调试程序,我们往往会写很多print打印输出以便用于验证,验证正确后往往会注释掉,一旦验证的地方比较多,再一一注释比 ...

  5. day09作业

    一.填空题 1.方法 2.堆内存 3.构造方法 4.this 5.this 6.static 7.使用类名进行访问 8.package import class 9.关键字 10.lang 二.选择题 ...

  6. FFmpeg命令行工具和批处理脚本进行简单的音视频文件编辑

    FFmpeg_Tutorial FFmpeg工具和sdk库的使用demo 一.使用FFmpeg命令行工具和批处理脚本进行简单的音视频文件编辑 1.基本介绍 对于每一个从事音视频技术开发的工程师,想必没 ...

  7. 洛谷P2746校园网

    传送门啦 下面来看任务B.我们发现,图中只要存在入度为0的点和出度为0的点就永远不可能满足要求:" 不论我们给哪个学校发送新软件,它都会到达其余所有的学校 ".我们还发现,只要在入 ...

  8. JS、JQ实现焦点图轮播效果

    JS实现焦点图轮播效果 效果图: 代码如下,复制即可使用: (不过里面的图片路径需要自己改成自己的图片路径,否则是没有图片显示的哦) <!DOCTYPE html> <html> ...

  9. CxGrid 表格标题头居中

    选中这些列后 搞.

  10. MyBatis的动态插入语句(经常报‘无效的列类型’)

    最近在工作中经常遇到一个情况:通过mybatis的标签执行插入语句,当表中字段比较多的时候,需要全部插入,而有时候的需求是只插入其中几个字段,但是会报错. 原来的语句,必须把所有字段都Set值. &l ...