DARK的锁链
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的锁链的更多相关文章
- Dark的项链(树链剖分)
P2272 - Dark的锁链 Description 无向图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边.Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由 ...
- 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)
最新的效果见 :http://video.sina.com.cn/v/b/124538950-1254492273.html 可处理视频的示例:视频去雾效果 在图像去雾这个领域,几乎没有人不知道< ...
- 微信小程序想要的是无法监测的流量dark social
“微信小程序”将带来什么样的变化?就单单的是一个超级Web app?还是只是为了给大家手机节省一些空间?腾讯想要的是高达70%以上的“无法监测的巨大流量”,称之为“dark social”(暗社交). ...
- MWeb 1.6 发布!Dark Mode、全文搜寻、发布到Wordpress、Evernote 等支持更新、编辑/预览视图模式等
Dark Mode 使用 View - Dark Mode 或快捷键 CMD + Option + L 开启或关闭 Dark Mode.可以在设置中设置 Dark Mode 状态下编辑器所使用的样式, ...
- 在Visual Studio 2012 Blue theme下使用Dark theme的文本编辑器颜色设置
Visual Studio 2012 默认提供了3种color theme: blue,light,和dark.其中dark的文本编辑器颜色设定很爽,可是整个菜单项加上一些小的窗口如Find Resu ...
- 保护眼睛,把常用软件的背景设置成Dark
每天长时间使用电脑,很多软件的背景都是白色,久看对眼睛不好. 1)Google Chrome,WebDev/看新闻/看邮件/写博客.使用Stylish插件和Global Dark Style,效果相当 ...
- paper 105: 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果及其他
在图像去雾这个领域,几乎没有人不知道<Single Image Haze Removal Using Dark Channel Prior>这篇文章,该文是2009年CVPR最佳论文.作者 ...
- 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 ...
- hdu 2988 Dark roads
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2988 Dark roads Description Economic times these days ...
随机推荐
- HQL连接查询
HQL提供了连接查询机制如内连接,外连接,,还允许显示指定迫切内连接,和迫切外联结. 连接类型 内连接 inner join 或join 迫切内链接 inner join fetch 左外联结 le ...
- 基于python的互联网软件测试开发(自动化测试)-全集合
基于python的互联网软件测试开发(自动化测试)-全集合 1 关键字 为了便于搜索引擎收录本文,特别将本文的关键字给强调一下: python,互联网,自动化测试,测试开发,接口测试,服务测试,a ...
- JS - What does `void 0` mean?
语法 void expression // or void(expression) MDN的描述 能向期望一个表达式的值是 undefined 的地方插入会产生副作用的表达式.也就是为了避免产生某种副 ...
- uml系列(七)——交互图
交互图是uml中描述系统中的对象如何进行交互动作的 . 废话不多说,还是来张图: 概念 交互图,主要描述的是系统中的一组对象的消息的传递的,为对象间的交互定义了一个可视的表示方法. ...
- Struts2系列笔记(4)---Ation类访问servlet
Ation类访问servlet Ation类有三种方式servlet: (1)间接的方式访问Servlet API ---使用ActionContext对象 (2) 实现接口,访问Action时完 ...
- 初学jQuery之jQuery事件与动画
今天我们就谈谈jquery中的事件和简单动画吧,它们毕竟基础是进阶华丽的根本!! 1.事件 1.window事件 ready 准备就绪 2.鼠标事件 方法 ...
- 简述.jpg .Gif .png-8 .png-24的区别
最近有很多朋友在开发过程中有时候会遇到图片加载不清晰,透明度失真,或者对图片进行操作之后造成图片损耗的现象,在这里给大家简单介绍一下常用的几种图片格式之间的区别 Gif格式特点: 1.透明性,Gif是 ...
- c++ 调用dl里的导出类
来源:http://blog.csdn.net/yysdsyl/article/details/2626033 动态dll的类导出:CPPDll2->test.h #pragma once // ...
- Java编程风格学习(三)
在上一篇的java编程风格学习(二)中我们学习了一些在Java编码过程中的格式规范,遵循这些规范毋庸置疑是我们的书写高质量代码的前提与基础.今天我们更进一步,一起来学习Java编程的命名规范,向着编写 ...
- iOS仿微博客户端一条微博的布局
前言 做一个微博客户端的第三方是自学的第一个实践的项目,自从从事iOS工作之后,就把这个项目给搁置了.趁现在过年回来有些空闲时间,再次修改(总觉得项目就是不停地修改).并且记录一点东西,以后可再回头看 ...