Description

无向图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark还有M条附加边。
你的任务是把Dark斩为不连通的两部分。一开始Dark的附加边都处于无敌状态,你只能选择一条主要边切断。一旦你切断了一条主要边,Dark就会进入防御模式,主要边会变为无敌的而附加边可以被切断。但是你的能力只能再切断Dark的一条附加边。现在你想要知道,一共有多少种方案可以击败Dark。注意,就算你第一步切断主要边之后就已经把Dark斩为两截,你也需要切断一条附加边才算击败了Dark。

Input

第一行包含两个整数N和M。
之后N – 1行,每行包括两个整数A和B,表示A和B之间有一条主要边。
之后M行以同样的格式给出附加边。

Output

输出一个整数表示答案。

Sample Input

4 1
1 2
2 3
1 4
3 4

Sample Output

3

Hint

对于20% 的数据,N≤100,M≤100。
对于100% 的数据,N≤100 000,M≤200 000。数据保证答案不超过2^31– 1。

题解:

对于每一条主要边,讨论被几条附加边覆盖

若没有附加边覆盖则去掉这条主要边后,DARK已经成了不连通的两部分,则只需切掉任意一条附加边,对答案贡献m

若被一条附加边覆盖,则去掉条主要边后必须去掉这条附加边,对答案贡献1

若被大于一条附加变覆盖,这不能被切成不连通的两部分

可以用每一个点代表与这个点的dad相连的边

做法一:树链剖分+线段树

每加入一条附加边时把两点之间的路径上的所有点在线段树中加上一,最后做n遍单点查询。

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<cctype>

#include<cfloat>

#include<vector>

#include<map>

#define ls o*2

#define rs o*2+1

#define mi int mid=(l+r)>>1

#define maxn 100010

using namespace std;

struct data{

  int nex,to;

}e[maxn*2];

int head[maxn],edge=0;

int top[maxn],deep[maxn],son[maxn],dad[maxn],size[maxn],sp[maxn];

bool co[maxn];int b[maxn*4],lazy[maxn*4],siz[4*maxn],n;

void build(int o,int l,int r)

{

  siz[o]=r-l+1;

  if(l==r) return;

  mi;

  build(ls,l,mid);

  build(rs,mid+1,r);

}

void add(int from,int to)

{

  e[++edge].nex=head[from];

  e[edge].to=to;

  head[from]=edge;

}

void dfs1(int x)

{

  if(co[x]) return;

  co[x]=1;

  size[x]=1;

  for(int i=head[x];i;i=e[i].nex)

    {

      int u=e[i].to;

      if(co[u])continue;

      dad[u]=x;

      deep[u]=deep[x]+1;

      dfs1(u);

      size[x]+=size[u];

      if(size[son[x]]<size[u]) son[x]=u;

    }

}

int de=0;

void dfs2(int x)

{

  if(co[x] || x==0) return;

  co[x]=1;

  sp[x]=++de;

  top[son[x]]=top[x];

  dfs2(son[x]);

  for(int i=head[x];i;i=e[i].nex)

    {

      int u=e[i].to;

      if(co[u] || u==son[x]) continue;

      top[u]=u;

      dfs2(u);

    }

}

void down(int o)

{

  b[ls]+=lazy[o]*siz[ls],b[rs]+=lazy[o]*siz[rs];

  lazy[ls]+=lazy[o],lazy[rs]+=lazy[o];

  lazy[o]=0;

}

void change(int o,int l,int r,int u,int v)

{

  if(l!=r) down(o);

  if(u>v) return;

  if(l>=u&&r<=v) {b[o]+=siz[o];lazy[o]+=1;return;}

  if(l>v || r<u) return;mi;

  if(v<=mid) change(ls,l,mid,u,v);

  else if(u>mid) change(rs,mid+1,r,u,v);

  else change(ls,l,mid,u,mid),change(rs,mid+1,r,mid+1,v);

}

void TREE_CUT(int x,int y)

{

  while(top[x]!=top[y]){

    if(deep[top[x]]>deep[top[y]]) change(1,1,n,sp[top[x]],sp[x]),x=dad[top[x]];

    else change(1,1,n,sp[top[y]],sp[y]),y=dad[top[y]];

  }

  if(deep[x]>deep[y]) swap(x,y);

  change(1,1,n,sp[x]+1,sp[y]);

}

int find(int o,int l,int r,int p)

{

  if(l!=r) down(o);

  if(l==r) return b[o];

  mi;

  if(p<=mid) return find(ls,l,mid,p);

  else return find(rs,mid+1,r,p);

}

int main()

{

  //freopen("!.in","r",stdin);

  //freopen("!.out","w",stdout);

  int m,x,y;

  scanf("%d%d",&n,&m);

  build(1,1,n);

  for(int i=1;i<n;i++)

    scanf("%d%d",&x,&y),add(x,y),add(y,x);

  top[1]=1,deep[1]=1,dad[1]=1;

  dfs1(1);memset(co,0,sizeof(co));dfs2(1);

  for(int i=1;i<=m;i++)

    scanf("%d%d",&x,&y),TREE_CUT(x,y);

  int ans=0;

  for(int i=2;i<=n;i++)

    {

      int op=find(1,1,n,sp[i]);

      if(op==1) ans+=1;

      if(op==0) ans+=m;

    }

  printf("%d\n",ans);

  return 0;

}

做法二:树链剖分+树上差分

注意到只有区间修改和单点查询,这很容易想到差分,只要将树剖成链,然后就和链上的差分一样的了。

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<cctype>

#include<cfloat>

#include<vector>

#include<map>

#define ls o*2

#define rs o*2+1

#define mi int mid=(l+r)>>1

#define maxn 100010

using namespace std;

struct data{

  int nex,to;

}e[maxn*2];

int head[maxn],edge=0;

int top[maxn],deep[maxn],son[maxn],dad[maxn],size[maxn],sp[maxn];

bool co[maxn];int b[maxn*4],lazy[maxn*4],siz[4*maxn],n,cha[maxn];

void add(int from,int to)

{

  e[++edge].nex=head[from];

  e[edge].to=to;

  head[from]=edge;

}

void dfs1(int x)

{

  if(co[x]) return;

  co[x]=1;

  size[x]=1;

  for(int i=head[x];i;i=e[i].nex)

    {

      int u=e[i].to;

      if(co[u])continue;

      dad[u]=x;

      deep[u]=deep[x]+1;

      dfs1(u);

      size[x]+=size[u];

      if(size[son[x]]<size[u]) son[x]=u;

    }

}

int de=0;

void dfs2(int x)

{

  if(co[x] || x==0) return;

  co[x]=1;

  sp[x]=++de;

  top[son[x]]=top[x];

  dfs2(son[x]);

  for(int i=head[x];i;i=e[i].nex)

    {

      int u=e[i].to;

      if(co[u] || u==son[x]) continue;

      top[u]=u;

      dfs2(u);

    }

}

void change(int x,int y)

{

  cha[x]++,cha[y+1]--;

}

void TREE_CUT(int x,int y)

{

  while(top[x]!=top[y]){

    if(deep[top[x]]>deep[top[y]]) change(sp[top[x]],sp[x]),x=dad[top[x]];

    else change(sp[top[y]],sp[y]),y=dad[top[y]];

  }

  if(deep[x]>deep[y]) swap(x,y);

  change(sp[x]+1,sp[y]);

}

int main()

{

 // freopen("!.in","r",stdin);

 // freopen("!.out","w",stdout);

  int m,x,y;

  scanf("%d%d",&n,&m);

  for(int i=1;i<n;i++)

    scanf("%d%d",&x,&y),add(x,y),add(y,x);

  top[1]=1,deep[1]=1,dad[1]=1;

  dfs1(1);memset(co,0,sizeof(co));dfs2(1);

  for(int i=1;i<=m;i++)

    scanf("%d%d",&x,&y),TREE_CUT(x,y);

  int ans=0;

  cha[1]=0;

  for(int i=2;i<=n;i++)

    {

      cha[i]+=cha[i-1];

      int op=cha[i];

      if(op==1) ans+=1;

      if(op==0) ans+=m;

    }

  printf("%d\n",ans);

  return 0;

}

DARK的锁链的更多相关文章

  1. Dark的项链(树链剖分)

    P2272 - Dark的锁链 Description 无向图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边.Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由 ...

  2. 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)

    最新的效果见 :http://video.sina.com.cn/v/b/124538950-1254492273.html 可处理视频的示例:视频去雾效果 在图像去雾这个领域,几乎没有人不知道< ...

  3. 微信小程序想要的是无法监测的流量dark social

    “微信小程序”将带来什么样的变化?就单单的是一个超级Web app?还是只是为了给大家手机节省一些空间?腾讯想要的是高达70%以上的“无法监测的巨大流量”,称之为“dark social”(暗社交). ...

  4. MWeb 1.6 发布!Dark Mode、全文搜寻、发布到Wordpress、Evernote 等支持更新、编辑/预览视图模式等

    Dark Mode 使用 View - Dark Mode 或快捷键 CMD + Option + L 开启或关闭 Dark Mode.可以在设置中设置 Dark Mode 状态下编辑器所使用的样式, ...

  5. 在Visual Studio 2012 Blue theme下使用Dark theme的文本编辑器颜色设置

    Visual Studio 2012 默认提供了3种color theme: blue,light,和dark.其中dark的文本编辑器颜色设定很爽,可是整个菜单项加上一些小的窗口如Find Resu ...

  6. 保护眼睛,把常用软件的背景设置成Dark

    每天长时间使用电脑,很多软件的背景都是白色,久看对眼睛不好. 1)Google Chrome,WebDev/看新闻/看邮件/写博客.使用Stylish插件和Global Dark Style,效果相当 ...

  7. paper 105: 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果及其他

    在图像去雾这个领域,几乎没有人不知道<Single Image Haze Removal Using Dark Channel Prior>这篇文章,该文是2009年CVPR最佳论文.作者 ...

  8. How to change statusbar text color to dark on android 4.4

    Because I haven't enough votes, so post picture at here, thank you. Almost 2 weeks ago, I was search ...

  9. hdu 2988 Dark roads

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2988 Dark roads Description Economic times these days ...

随机推荐

  1. HttpClient 4.3连接池参数配置及源码解读

    目前所在公司使用HttpClient 4.3.3版本发送Rest请求,调用接口.最近出现了调用查询接口服务慢的生产问题,在排查整个调用链可能存在的问题时(从客户端发起Http请求->ESB-&g ...

  2. BZOJ两水题连发~(BZOJ1854&&BZOJ1191)

    前言:两题都是省选题不过水的惊人,且都可以用二分图最大匹配做哎--- 1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: ...

  3. 常用js类型相互转换

    数字转换为字符串 var a=200.21;document.write(a.toString(10));  结果为:200.21以十进制转换 document.write(a.toFixed(3)) ...

  4. OpenLayers.Map的一些特殊事件

    开年上班的第二天,无意中看到一些没见过的事件,特地来给广大人民群众报个信. 众所周知的,map里面的 eventListeners 支持的事件挺多的,比如: var map = new OpenLay ...

  5. CentOS 7 网卡命名修改为ethx格式

    Linux 操作系统的网卡设备的传统命名方式是 eth0.eth1.eth2等,而 CentOS7 提供了不同的命名规则,默认是基于固件.拓扑.位置信息来分配.这样做的优点是命名全自动的.可预知的,缺 ...

  6. context:annotation-config, mvc:annotation-driven, context:compont-scan 区别

    当我们需要使用BeanPostProcessor时,直接在Spring配置文件中定义这些Bean显得比较笨拙,例如: 使用@Autowired注解,必须事先在Spring容器中声明AutowiredA ...

  7. block之---数据传递

    block值传递分为两种情况 1.值传递 含义: 类似于函数参数的值传递,block内部对值的改变对外部没有影响,外部改变对block内部也没有影响. 情况 block访问外部局部变量没有被任何关键字 ...

  8. java byte【】数组与文件读写

    此文全文参考http://blog.csdn.net/sniffer_wang/article/details/7455701,自己加以改进应用,谢了 import java.io.ByteArray ...

  9. Ceph BlueStore 解析:Object IO到磁盘的映射

    作者:吴香伟 发表于 2017/02/19 版权声明:可以任意转载,转载时务必以超链接形式标明文章原始出处和作者信息以及版权声明 简单回顾下Ceph OSD后端存储引擎的历史. 为解决事务原子性问题, ...

  10. STM32按键控制程序

    由于最近时间比较匆忙 已经有很久的时间没有写博客了 这次和大家分享的是STM32的一个按键的小程序 他的优点呢也是和上面一个LED一样就是便于移植 更改管脚方便 虽然都是些小程序 但是我觉得他们就像基 ...