HDU 6203 ping ping ping [LCA+dfs序+树状数组]
2017-09-13 13:15
393 查看
题意:给你一颗n+1个节点的树,有q个条件,每个条件需要破坏一些点使得u和v不连通。
题解:由于是一棵树,那么最下面的点对的路径肯定是越往上破坏越优,所以我们考虑所有条件u和v的LCA,按照LCA的深度排序开始破坏。
但是如何知道u到v的路径上是否已经有点破坏呢?我们用不同于一般的dfs序记录,例如下图:
![](https://img-blog.csdn.net/20170913130444047?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQUNUZXJtaW5hdGU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
一般dfs序只记录先序:
![](https://img-blog.csdn.net/20170913130633687?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQUNUZXJtaW5hdGU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这里用到的dfs序也同时记录点返回时候的序:
![](https://img-blog.csdn.net/20170913131101936?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQUNUZXJtaW5hdGU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
当我们需要访问4和3的时候:
我们相当于询问区间[in[4],out[2]]与[in[3],out[2]]。(得到路径2到4和路径2到3上破坏点的个数)
若要插入的时候我们将in[u]加1,out[u]减一就可以了。
AC代码:
题解:由于是一棵树,那么最下面的点对的路径肯定是越往上破坏越优,所以我们考虑所有条件u和v的LCA,按照LCA的深度排序开始破坏。
但是如何知道u到v的路径上是否已经有点破坏呢?我们用不同于一般的dfs序记录,例如下图:
一般dfs序只记录先序:
这里用到的dfs序也同时记录点返回时候的序:
当我们需要访问4和3的时候:
我们相当于询问区间[in[4],out[2]]与[in[3],out[2]]。(得到路径2到4和路径2到3上破坏点的个数)
若要插入的时候我们将in[u]加1,out[u]减一就可以了。
AC代码:
#include<stdio.h> #include<algorithm> #include<vector> #include<string.h> #define N 10005 using namespace std; struct node { int u,v; int lca; }qq[50005]; vector<int>vt ; int c[N*2]; int in ,out ,deep ,n; int p [20]; int tot=0; void dfs(int u,int FA,int dep) { in[u]=++tot; deep[u]=dep; p[u][0]=FA; for(int i=0;i<vt[u].size();i++) { int to=vt[u][i]; if(to==FA)continue; dfs(to,u,dep+1); } out[u]=++tot; } void init() { int i,j; //p[i][j]表示i结点的第2^j祖先 for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) if(p[i][j-1]!=-1) p[i][j]=p[p[i][j-1]][j-1]; //i的第2^j祖先就是i的第2^(j-1)祖先的第2^(j-1)祖先 } int lca(int a,int b) {//最近公共祖先 int i,j; if(deep[a]<deep[b])swap(a,b); for(i=0;(1<<i)<=deep[a];i++); i--; for(j=i;j>=0;j--) //使a,b两点的深度相同 if(deep[a]-(1<<j)>=deep[b]) a=p[a][j]; if(a==b)return a; for(j=i;j>=0;j--) { if(p[a][j]!=-1&&p[a][j]!=p[b][j]) { a=p[a][j]; b=p[b][j]; } } return p[a][0]; } bool cmp(node a,node b) { return deep[a.lca]>deep[b.lca]; } int lowbit(int i) { return i&(-i); } int sum(int i) { int ans=0; while(i) { ans+=c[i]; i-=lowbit(i); } return ans; } int change(int i,int k) { while(i<=2*n) { c[i]+=k; i+=lowbit(i); } } int main() { while(~scanf("%d",&n)) { tot=0; memset(p,0,sizeof(p)); memset(c,0,sizeof(c)); for(int i=0;i<10005;i++) vt[i].clear(); for(int i=0;i<n;i++) { int u,v; scanf("%d%d",&u,&v); u++;v++; vt[u].push_back(v); vt[v].push_back(u); //printf(">>%d %d\n",u,v); } n++; dfs(1,1,1); init(); int q; scanf("%d",&q); for(int i=0;i<q;i++) { scanf("%d%d",&qq[i].u,&qq[i].v); qq[i].u++;qq[i].v++; qq[i].lca=lca(qq[i].u,qq[i].v); } sort(qq,qq+q,cmp); int ans=0; for(int i=0;i<q;i++) { int u=qq[i].u,v=qq[i].v,lc=qq[i].lca; if((sum(in[u])-sum(out[lc])+sum(in[v])-sum(out[lc])))continue; else { ans++; change(in[lc],1); change(out[lc],-1); } } printf("%d\n",ans); } }
相关文章推荐
- HDU 6203 ping ping ping (LCA+DFS序)
- HDU 6203 ping ping ping(在线倍增LCA+BIT)
- HDU 6203 ping ACM/ICPC 2017 Shenyang Online(LCA+贪心)
- HDU 6203 ping ping ping (LCA + 树状数组, 2017 ACM/ICPC Asia Regional Shenyang Online)
- HDU 6203 ping ping ping lca 线段树成段更新
- hdu 6203 ping ping ping(LCA+树状数组)
- [HDU 6203] ping ping ping
- hdu 6203 ping ping ping(贪心+树状数组+dfs序)
- HDU 6203 ping ping ping
- HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
- HDU 6203 ping ping ping(dfs序+LCA+树状数组)
- HDU 3830 - Checkers (LCA模型)
- HDU 3830 Checkers(二分+lca)
- 【Lca 离线Tarjan算法】hdu 2586 How far away ?
- HDU 3078 (LCA+树链第K大)
- hdu 5044 树区间操作最后输出/ lca+dfs
- HDU 4081 Qin Shi Huang's National Road System 最小生成树+倍增求LCA
- HDU 6065 RXD, tree and sequence (LCA DP)
- hdu 6115 Factory(LCA+暴力)
- hdu 2586 How far away ?(LCA)