闇の連鎖
(yam.pas/c/cpp)
题目描述
传说中的暗之连锁被人们称为 Dark。Dark 是人类内心的
黑暗的产物,古今中外的勇者们都试图打倒它。经过研究,
你发现 Dark 呈现无向图的结构,图中有 N 个节点和两类边,
一类边被称为主要边,而另一类被称为附加边。Dark 有 N – 1
条主要边,并且 Dark 的任意两个节点之间都存在一条只由主
要边构成的路径。另外,Dark 还有 M 条附加边。
你的任务是把 Dark 斩为不连通的两部分。一开始 Dark
的附加边都处于无敌状态,你只能选择一条主要边切断。一
旦你切断了一条主要边,Dark 就会进入防御模式,主要边会变为无敌的而附加边可以被切
断。但是你的能力只能再切断 Dark 的一条附加边。现在你想要知道,一共有多少种方案可
以击败 Dark。注意,就算你第一步切断主要边之后就已经把 Dark 斩为两截,你也需要切断
一条附加边才算击败了 Dark。
输入格式
第一行包含两个整数 N 和 M。
之后 N – 1 行,每行包括两个整数 A 和 B,表示 A 和 B 之间有一条主要边。
之后 M 行以同样的格式给出附加边。
输出格式
输出一个整数表示答案。

显然,这个图上的点与主要边构成了一棵树。当加入一条附加边时,会构成环。如果我们第一次砍主要边的时候砍的是$x$->$y$路径上的某条边,那么之后再砍的附加边一定是$<x,y>$。

这样,我们的题目就转换成了一个树上差分的问题。附加边$<x,y>$会影响x到y路径上的所有边。把这些边经过的次数(受影响的次数)进行统计。若第一次砍的是覆盖0次的,那么第二步可任意切断一条附加边;若一次砍的 是覆盖1次的,第二步方法唯一;其他答案在第二步均没有其他任何方法。

实现的时候dfs和lca查询写错了两个细节,结果调了很久...气orz

Code

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<queue>
  4. #include<cmath>
  5. #define maxn 100090
  6.  
  7. using namespace std;
  8.  
  9. int n,m,tot,t,ans;
  10. int head[maxn],d[maxn],f[maxn][],val[maxn];
  11. struct node{
  12. int to,next;
  13. }edge[maxn*];
  14.  
  15. void add(int x,int y)
  16. {
  17. edge[++tot].to=y;
  18. edge[tot].next=head[x];
  19. head[x]=tot;
  20. }
  21.  
  22. void init()
  23. {
  24. queue<int>q;
  25. q.push(),d[]=;
  26. while(!q.empty())
  27. {
  28. int u=q.front();q.pop();
  29. for(int i=head[u];i;i=edge[i].next)
  30. {
  31. int v=edge[i].to;
  32. if(d[v]) continue;
  33. d[v]=d[u]+;
  34. f[v][]=u;
  35. for(int j=;j<=t;j++)
  36. f[v][j]=f[f[v][j-]][j-];
  37. q.push(v);
  38. }
  39. }
  40. }
  41.  
  42. int lca(int x,int y)
  43. {
  44. if(d[x]>d[y]) swap(x,y);
  45. for(int i=t;i>=;i--)
  46. if(d[f[y][i]]>=d[x]) y=f[y][i];
  47. if(x==y) return x;
  48. for(int i=t;i>=;i--)
  49. if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
  50. return f[x][];
  51. }
  52.  
  53. void review(int u,int fa)
  54. {
  55. for(int i=head[u];i;i=edge[i].next)
  56. {
  57. int v=edge[i].to;
  58. if(v==fa) continue;
  59. review(v,u);
  60. val[u]+=val[v];
  61. }
  62. }
  63.  
  64. int main()
  65. {
  66. scanf("%d%d",&n,&m);
  67. t=log2(n)+;
  68. for(int i=;i<=n-;i++)
  69. {
  70. int x=,y=;
  71. scanf("%d%d",&x,&y);
  72. add(x,y);add(y,x);
  73. }
  74. init();
  75. for(int i=;i<=m;i++)
  76. {
  77. int x=,y=;
  78. scanf("%d%d",&x,&y);
  79. int fa=lca(x,y);
  80. val[x]++,val[y]++;
  81. val[fa]-=;
  82. }
  83. review(,);
  84. for(int i=;i<=n;i++)
  85. {
  86. if(val[i]==) ans+=m;
  87. else if(val[i]==) ans++;
  88. }
  89. printf("%d\n",ans);
  90. return ;
  91. }

poj3417 闇の連鎖 【树上差分】By cellur925的更多相关文章

  1. poj3417 Network/闇の連鎖[树上差分]

    首先隔断一条树边,不计附加边这个树肯定是断成两块了,然后就看附加边有没有连着的两个点在不同的块内. 方法1:BIT乱搞(个人思路) 假设考虑到$x$节点隔断和他父亲的边,要看$x$子树内有没有点连着附 ...

  2. poj3417 Network——LCA+树上差分

    题目:http://poj.org/problem?id=3417 根据一条边被几个环覆盖来判断能不能删.有几种情况等: 用树上差分,终点 s++,LCA s-=2,统计时计算子树s值的和即可: 用S ...

  3. poj3417 Network 树上差分+LCA

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

  4. 序列/树上差分小结 By cellur925

    首先我们需要注意一下的是,差分比较适用于修改比较多而查询比较少的情况. 一.序列上差分 借教室  这是一道二分答案,在check函数中用到差分技巧的一道题,譬如说我们要把一个序列中[l,r]区间都加上 ...

  5. [POJ3417]Network(LCA,树上差分)

    Network Description Yixght is a manager of the company called SzqNetwork(SN). Now she's very worried ...

  6. 【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)

    POJ3417:http://poj.org/problem?id=3417 思路 我们注意到由“主要边”构成一颗树 “附加边”则是非树边 把一条附加边(x,y)加入树中 会与树上x,y之间构成一个环 ...

  7. 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 703  Solved: 461[Submit][Status] ...

  8. [luogu P3128][USACO15DEC]Max Flow [LCA][树上差分]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  9. 树上差分 (瞎bb) [树上差分][LCA]

    做noip2015的运输计划写了好久好久写不出来   QwQ 于是先来瞎bb一下树上差分    混积分 树上差分有2个常用的功能: (1)记录从点i到i的父亲这条路径走过几次 (2)将每条路径(s,t ...

随机推荐

  1. NYOJ 1067 Compress String(区间dp)

    Compress String 时间限制:2000 ms  |  内存限制:65535 KB 难度:3 描写叙述 One day,a beautiful girl ask LYH to help he ...

  2. linux输入子系统(5) - 学习框架

    注:本系列转自: http://www.ourunix.org/post/290.html input子系统学习系列文章,是我在实际开发过程中遇到也是必须啃下去的第一个Linux驱动,所以有必要记载下 ...

  3. C++类中使用new及delete小例子

    //默认复制构造函数的不足//尽管有默认的复制构造函数来解决一般对象与对象之间的初始化问题, 但是在有些情况下我们必须手动显式的去定义复制构造函数, 例如: #include <iostream ...

  4. atitit.eclipse有多少api&#160;&#160;扩展点,以及扩展点的设计

    atitit.eclipse有多少api  扩展点,以及扩展点的设计 不赞成使用的.作废的以及内部的扩展点 [扩展]页显示了几个你不应该在你的插件中使用的扩展点.在附表C.1的[描写叙述]栏中.我们使 ...

  5. MVC Controller构造器注入

    UnityDependencyResolver 的标准写法 public class UnityDependencyResolver : IDependencyResolver {     priva ...

  6. C# 软件实现远程桌面调用

    1.https://www.codeproject.com/Articles/19836/Palantir-Remote-Desktop-Manager codeproject项目 2.http:// ...

  7. 迭代器模式(Iterator.hasNaxt())

    迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式.这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示. 迭代器模式属于行为型模式. ...

  8. ios 关于动画用法的总结

      #import "FirstVC.h" @implementation FirstVC /*     创建xib过程     1 创建xib(名字和类名相同)     2 文件 ...

  9. I.MX6 sdio 设备注册及识别

    /************************************************************************* * I.MX6 sdio 设备注册及识别 * 说明 ...

  10. 深入理解dispatch_sync

    关于GCD的基础知识,之前写过一篇博客,详见GCD基础知识.虽然之前已经梳理过了,但对很多知识点的理解仍然不够透彻…写这篇博客的原因是在阅读AFNetworking代码时遇到一些奇怪的代码. 如下: ...