题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案。

神题,一点也想不到做法,

首先要分析出加入一条边之后会形成环,形成环的话,如果去掉该边和环上面没有被其他环覆盖的边,那么便分为两部分了。

这样只需要记录每条边被环覆盖了几次即可,

用dp[u]表示u点的父边被覆盖了几次。

每次新加进来一条边(a,b) dp[a] ++ ,dp[b] ++ , dp[lca(a,b)] -= 2;

所有边处理完之后,遍历一边此树,同时转移状态 dp[u] += dp[v];

  1. #define maxn 100005
  2.  
  3. struct node
  4. {
  5. int v,next;
  6. };
  7. node e[maxn * ];
  8. int cnt ;
  9. int head[maxn * ];
  10. int num ;
  11. int E[maxn * + ],L[maxn * + ],R[maxn * + ];
  12. int f[maxn * + ][];
  13. int dp[maxn];
  14. void init()
  15. {
  16. cnt = ;
  17. memset(head,-,sizeof(head));
  18. }
  19. void add(int u ,int v)
  20. {
  21. e[cnt].v = v ;
  22. e[cnt].next = head[u];
  23. head[u] = cnt ++ ;
  24. e[cnt].v = u;
  25. e[cnt].next = head[v] ;
  26. head[v] = cnt ++ ;
  27. return ;
  28. }
  29. void dfs(int u ,int fa,int dep)
  30. {
  31. E[++num] = u , L[num] = dep , R[u] = num;
  32. for(int i = head[u] ;i != -; i = e[i].next)
  33. if(e[i].v != fa)
  34. {
  35. int v = e[i].v;
  36. dfs(v, u, dep + );
  37. E[++num] = u , L[num] = dep;
  38. }
  39. return;
  40. }
  41. void initRMQ()
  42. {
  43. for(int i = ; i <= num ;i ++ ) f[i][] = i;
  44. for(int j = ; (<<j) <= num ; j++ )
  45. for(int i = ; i + (<<j) - <= num; i ++ )
  46. if(L[f[i][j-]] < L[f[i+(<<(j-))][j-]]) //ps:注意下标
  47. f[i][j] = f[i][j-];
  48. else f[i][j] = f[i+(<<(j-))][j-];
  49. }
  50. int lca(int a ,int b)
  51. {
  52. a = R[a] , b = R[b];
  53. if(a>b) swap(a,b);
  54. int k = (log(1.0 + b - a )/log(2.0));
  55. if(L[f[a][k]] < L[f[b-(<<k)+][k]] )
  56. return E[f[a][k]];
  57. else return E[f[b-(<<k)+][k]];
  58. }
  59. void dfs(int u,int fa)
  60. {
  61. for(int i = head[u] ; i != - ; i =e[i].next)
  62. if(e[i].v != fa)
  63. {
  64. int v = e[i].v;
  65. dfs(v,u);
  66. dp[u] += dp[v];
  67. }
  68. return ;
  69. }
  70. int main()
  71. {
  72. int n,m;
  73. int u,v;
  74. while(scanf("%d%d",&n,&m)!=EOF)
  75. {
  76. init();
  77. for(int i = ; i < n - ; i ++ )
  78. {
  79. scanf("%d%d",&u,&v);
  80. add(u,v);
  81. }
  82. num = ;
  83. memset(R,,sizeof(R));
  84. dfs(,,);
  85. initRMQ();
  86. memset(dp,,sizeof(dp));
  87. for(int i = ; i < m ; i ++ )
  88. {
  89. scanf("%d%d",&u,&v);
  90. dp[u] ++ ;
  91. dp[v] ++ ;
  92. dp[lca(u,v)] -= ;
  93. }
  94. dfs(,);
  95. int sum ;
  96. sum = ;
  97. for(int i = ;i <= n ; i++ ) // ps:1为根不要选。
  98. {
  99. if(dp[i] == )
  100. sum ++;
  101. else if(dp[i] == )
  102. sum += m;
  103. }
  104. printf("%d\n",sum);
  105. }
  106. return ;
  107. }
  108.  
  109. /*
  110. 好题:
  111. 离线LCA + 树形DP
  112.  
  113. 分析:加进来一条边(a,b),会形成一条环 a - lca(a,b) - b
  114. 如果去掉(a,b)和没有被其他环覆盖的边,那么就能把树分成两部分。
  115. 只要记录dp[u]表示u的负边被环覆盖了几次
  116. 对于新加进来的一条边(a,b) dp[a] ++ , dp[b] ++ , dp[lca(a,b)] -= 2;///
  117. 这样处理为完所有新加进来的边之后,在dfs一边,跑完状态转移:dp[u] += dp[v];
  118. 这里就可以把每条环上的边都依次加1,并且因为lca(a,b)的父边不再环上,且已经提前减去了2
  119. 这样转移正好可以把减掉的2消去。
  120.  
  121. 注意:这里把lca离线处理成rmq,只需要O(n)的遍历和O(nlogn)的预处理即可。 ST表
  122.  
  123. 并且这里以1为根,后面的状态转移也要以1为根,否则lca就白算了。
  124.  
  125. */

poj3417

poj3417 Network 树形Dp+LCA的更多相关文章

  1. SGU 149. Computer Network( 树形dp )

    题目大意:给N个点,求每个点的与其他点距离最大值 很经典的树形dp...很久前就想写来着...看了陈老师的code才会的...mx[x][0], mx[x][1]分别表示x点子树里最长的2个距离, d ...

  2. hdu_5293_Tree chain problem(DFS序+树形DP+LCA)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5293 被这题打蹦了,看着题解写的,很是爆炸,确实想不到,我用的DFS序+LCA+树形DP,当然也可以写 ...

  3. Uva LA 3902 - Network 树形DP 难度: 0

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  4. poj 3417 树形dp+LCA

    思路:我以前一直喜欢用根号n分段的LCA.在这题上挂了,第一次发现这样的LCA被卡.果断改用Tarjan离线算法求LCA. 当前节点为u,其子节点为v.那么: 当以v根的子树中含有连接子树以外点的边数 ...

  5. poj3417 Network 树上差分+LCA

    题目传送门 题目大意:给出一棵树,再给出m条非树边,先割掉一条树边,再割掉一条非树边,问有几种割法,使图变成两部分. 思路:每一条 非树边会和一部分的树边形成一个环,分三种情况: 对于那些没有形成环的 ...

  6. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  7. Codeforces Round #343 (Div. 2) E. Famil Door and Roads (树形dp,lca)

    Famil Door's City map looks like a tree (undirected connected acyclic graph) so other people call it ...

  8. HDU4008 Parent and son(树形DP LCA)

    先记录以1为根时每个节点子树儿子节点的最大与次小值,询问x, y时,先判断x在不在y的子树范围内,若不在,结果为y的儿子结点,后继的最小值. 若x在y的子树范围内,若y儿子最小值是x的前驱,从次小值与 ...

  9. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

随机推荐

  1. [置顶] 最优间隔分类器、原始/对偶问题、SVM的对偶问题——斯坦福ML公开课笔记7

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9774135 本篇笔记针对ML公开课的第七个视频,主要内容包括最优间隔分类器( ...

  2. HDU 1856 More is better(并查集+离散化)

    题目地址:HDU 1856 水题.因为标号范围太大,而数据数仅仅有10w,所以要先进行离散化.然后就是裸的并查集了. 代码例如以下: #include <iostream> #includ ...

  3. Google Maps Android API v2 (4)- 地图类型

    地图类型 地图内的谷歌地图的Android API的种类有很多.地图的类型管辖地图的整体代表性.例如,地图集通常包含政治地图,专注于显示边界和道路地图,显示了一个城市或地区的所有道路. Android ...

  4. [TWRP 2.8.4 ] 小米 3W 中文-英文版本 twrp

    经过半个小时的代码修改,从 2.7.0 移植到 2.8.4 的源代码上. 汉化操作是使用切换语言选项来实现的. 注意: 此版本的 twrp 还不支持双系统切换功能. 作者:laser杨万荣 如果需要转 ...

  5. 十大经典数据挖掘算法(9) 朴素贝叶斯分类器 Naive Bayes

    贝叶斯分类器 贝叶斯分类分类原则是一个对象的通过先验概率.贝叶斯后验概率公式后计算,也就是说,该对象属于一类的概率.选择具有最大后验概率的类作为对象的类属.现在更多的研究贝叶斯分类器,有四个,每间:N ...

  6. 我已提取并尝试使用启动脚本(./start navicat)来启动 Navicat Linux 版本号,但没有反应

    具体的安装教程,參考这个navicat_for_mysql_10.0.11在linux下的安装,介绍的非常具体 參考这个 :我可否在 64-bit Linux 执行 Navicat? 推荐navica ...

  7. MSSQL连接字符串,你真的清楚吗?

    原文:MSSQL连接字符串,你真的清楚吗? 几年前当我第一次面试时,考官发现我是个新手于是他让我写个连接字符串,虽然当时就知道X种连接字符串的写法,但是当时却没能写对一个,工作多年后我仍然不能写一个正 ...

  8. php 两个文件之间的相对路径的计算方法

    php 两个文件之间的相对路径的计算方法 比如: 文件A 的路径是 /home/web/lib/img/cache.php 文件B的路径是 /home/web/api/img/show.php 那么. ...

  9. uva133 The Dole Queue ( 约瑟夫环的模拟)

    题目链接: 啊哈哈,选我选我 思路是: 相当于模拟约瑟夫环,仅仅只是是从顺逆时针同一时候进行的,然后就是顺逆时针走能够编写一个函数,仅仅只是是走的方向的标志变量相反..还有就是为了(pos+flag+ ...

  10. 上curl java 模拟http请求

    最近,我的项目要求java模拟http请求,获得dns解决 tcp处理过的信息特定的连接. java api提供urlConnection apache提供的httpClient都不能胜任该需求,二次 ...