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 ...
随机推荐
- hdoj 2674 N!
N!Again Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- fir.im Weekly - 可能是 2017 最好的 Swift 学习资源
春节假期刚结束,一大批新鲜干货就来了.@故胤道长 分享了一份开源 Swift30 Projects ,内含 30 个小App,更新至 Swift 3.0,目前更迭的这个版本更注重代码规范和架构设计,且 ...
- 【Spring】使用Spring的AbstractRoutingDataSource实现多数据源切换
最近因为项目需要在做两个项目间数据同步的需求,具体是项目1的数据通过消息队列同步到项目2中,因为这个更新操作还涉及到更新多个库的数据,所以就需要多数据源切换的操作.下面就讲讲在Spring中如何进行数 ...
- Java安装
java特点:跨平台.简单.面向对像编译后解释再运行安装JDK 环境变量的配置:JAVA_HOME:JDK的根目录====C:\Program Files\Java\jdk1.7.0_25Path:J ...
- javascript组件的基本结构
(function(window, undefined) { function JsClassName(cfg) { var config = cfg || {}; this.get = functi ...
- Zigbee折腾之旅:(一)CC2530最小系统
最近在倒腾Zigbee,准备参加物联网全国大赛,学校有给我们发Zigbee开发板,但是对于喜欢折腾的我来说,用开发板还是不过瘾,起码也得知道怎么去画一块板子.于是乎,在百度一番后就有了下面这篇文章. ...
- 使用秘钥连接ssh
ssh服务器搭建 通过秘钥登陆连接另外一台虚拟机 创建证书 ssh-keygen -t rsa 第一行密钥保存位置直接输入回车 确定默认创建位置为 /root/.ssh 公钥必须改名为 autho ...
- Android SDK教程
Android SDK 网络问题解析 Android 客户端网络不稳定,会导致App 有时候无法及时收到 Push 消息. 很多开发者认为这是因为 JPush 推送不稳定.延迟,甚至有时候认为 JPu ...
- HTML5培训哪里靠谱
兄弟连IT培训教育,是学科最全的IT培训机构,涵盖HTML5培训.等学科,并是业内推出真实千万级服务器架构课程的唯一培训学校.兄弟连已分别在北京.上海.广州.沈阳.郑州.济南.成都.杭州.南京.南宁. ...
- MySQL Sniffer
MySQL Sniffer 是360开源的一个基于 MySQL 协议的抓包工具, 能实时抓取客户端端请求,并格式化输出操作语句,操作十分简单.对于问题的定位,操作的审核是个不错的利器. Github地 ...