jzoj5394 【NOIP2017提高A组模拟10.5】Ping
来源:互联网 发布:清华软件研究生怎么样 编辑:程序博客网 时间:2024/06/05 22:42
题面
分析
很容易看出模型:有若干条路径,选最少的点使得每条路径上都有点。并给出方案。
考虑一条链,其实就抽象成数轴上的线段。显然是贪心。(然而我最后五分钟才想起来!?
把线段按右端点从小到大排序,考虑右端点最左的一条线段,其他线段要么与他没有交集,要么从右边有交。那么这条线段取点一定是取右端点能覆盖更多的线段。
把覆盖掉的线段删除,重复上述步骤,直到覆盖完毕。
还能得出一个结论: 只选右端点。
对于树上的两条路径,我们知道路径A交路径B,要么A的lca在B上,要么B的lca在A上。
所以,对于一条Lca深度最大的路径,一定在他这选一个点(没有其他路径的lca在他上面)。 自然是选深度最小的lca最好了,这样能覆盖更多上面的路径。
证明嘛感性一点好了C(・ω・)ノ
所以拿个树剖维护下就好了。
Demo
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define lowbit(x) ((x)&-(x))using namespace std;const int N = 1e5 + 10;int n,m,k;int to[N*2],nex[N*2],final[N],tot;int dep[N],fa[N],top[N],size[N],hvy[N],loc[N];int ans[N],t[N];struct path{ int x,y,lca;} s[3*N];bool cmp(path a,path b) {return dep[a.lca]>dep[b.lca];}void link(int x,int y) { to[++tot]=y,nex[tot]=final[x],final[x]=tot;}void dfs(int x) { dep[x]=dep[fa[x]]+1; size[x]=1; for (int i=final[x]; i; i=nex[i]) { int y=to[i]; if (y==fa[x]) continue; fa[y]=x; dfs(y); size[x]+=size[y]; if (size[y]>size[hvy[x]]) hvy[x]=y; }}int stm;void build(int x) { loc[x]=++stm; if (!top[x]) top[x]=x; if (hvy[x]) top[hvy[x]]=top[x],build(hvy[x]); for (int i=final[x]; i; i=nex[i]) { if (to[i]!=fa[x] && to[i]!=hvy[x]) build(to[i]); }}int lca(int x,int y) { while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); x=fa[top[x]]; } return dep[x]>dep[y]?y:x;}void change(int x) { for (; x<=n; x+=lowbit(x)) t[x]++;}int sum(int x) { int sum=0; for (; x; x-=lowbit(x)) sum+=t[x]; return sum;}bool query(int x,int y) { while (top[x]!=top[y]) { if (sum(loc[x]) - sum(loc[top[x]]-1) > 0) return 1; x=fa[top[x]]; } if (sum(loc[x]) - sum(loc[y]-1) > 0) return 1; return 0;}int main() { freopen("ping.in","r",stdin); //freopen("ping.out","w",stdout); cin>>n>>m; for (int i=1; i<=m; i++) { int u,v; scanf("%d %d",&u,&v); link(u,v),link(v,u); } dfs(1); build(1); cin>>k; for (int i=1; i<=k; i++) { int x,y; scanf("%d %d",&s[i].x,&s[i].y); s[i].lca=lca(s[i].x,s[i].y); } sort(s+1,s+1+k,cmp); for (int i=1; i<=k; i++) { if (query(s[i].x,s[i].lca) + query(s[i].y,s[i].lca) == 0) { change(loc[s[i].lca]); ans[++ans[0]]=s[i].lca; } } cout<<ans[0]<<endl; for (int i=1; i<=ans[0]; i++) printf("%d\n",ans[i]);}
阅读全文
0 0
- jzoj5394 【NOIP2017提高A组模拟10.5】Ping
- [JZOJ5394]【NOIP2017提高A组模拟10.5】Ping
- JZOJ5394. 【NOIP2017提高A组模拟10.5】Ping 树上差分 树状数组
- 【NOIP2017提高A组模拟10.5】Ping
- 【NOIP2017提高A组模拟10.5】Ping
- 【NOIP2017提高A组模拟10.5】Ping
- 【JZOJ 5394】【NOIP2017提高A组模拟10.5】Ping
- JZOJ 5392. 【NOIP2017提高A组模拟10.5】Lucky Transformation
- 【NOIP2017提高A组模拟10.5】Snake vs Block
- A【NOIP2017提高组模拟12.18】
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高组模拟12.18】A
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高A组模拟7.7】图
- 【NOIP2017提高A组模拟7.13】abcd
- 区间【NOIP2017提高A组模拟7.10】
- 【NOIP2017提高A组模拟8.22】密码
- 【NOIP2017提高A组模拟8.23】密码
- 15算法课程 38. Count and Say
- openwrt关闭ssh功能
- GaoHash算法根据经纬度检索附近
- 素数筛法
- java经典笔试题目解析(下)
- jzoj5394 【NOIP2017提高A组模拟10.5】Ping
- 不同年龄段的孩子如何开始学习编程
- 114. Flatten Binary Tree to Linked List
- 9、super关键字
- 试题17:合并两个排序的链表
- 20个高级java开发面试题(带答案)
- HDOJ2065"红色病毒"问题
- chapter5:分类的进一步探讨---算法评估及kNN
- 10、多态