[bzoj1969][AHOI2005]LANE 航线规划
来源:互联网 发布:爱淘宝抢红包入口 编辑:程序博客网 时间:2024/04/28 15:34
题目大意
一个n个节点m条边的图,两点间的关键边定义为从一点走到另一个点必须经过的边。
现有许多操作,删一条边或者询问两点间的关键边数量。
保证任意时刻原图联通。
时间倒流
先把所有边删掉,然后倒着做,转删边为加边。
然后我们思考,最后原图也是联通的,那么做边双联通分量缩点后,就会变成一棵树。
然后显然两个结点间关键边数等于它们所处联通分量代表的点在树上树路径的边数。
然而我们要处理加边,每加一条边产生一个环,例如j与k(j与k指树中节点)间添加一条边,那么j到k路径上的所有点都处在一个环中,自然的,j到k路径上的所有边绝对不可能是关键边。
于是边给个边权,1代表是关建边0代表不是。
询问就是询问树中路径边权和,树链剖分维护。
修改就是路径上的边都赋值为0。
注意各种细节。。
怎么我代码那么丑写了230+行,陈主力比我少100行。
#include<cstdio>#include<algorithm>#include<map>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)#define fi first#define se secondusing namespace std;typedef pair<int,int> suan;map<suan,int> pos,sop;const int maxn=30000+10,maxm=100000+10;int fa[maxn][20],d[maxn];int h[maxn],belong[maxn],s[maxn],dfn[maxn],low[maxn],from[maxm*2],go[maxm*2],next[maxm*2];int size[maxn],jump[maxn];int h2[maxn],g2[maxn*2],n2[maxn*2];int q[maxn*2][4];int tree[maxn*4],set[maxn*4];bool bz[maxm],zb[maxm],pd[maxn],flag[maxn],bj[maxn*4];int i,j,k,l,t,n,m,tot,top,cnt,num,sum,euler;void add(int x,int y){ pos[make_pair(x,y)]=++tot; go[tot]=y; from[tot]=x; next[tot]=h[x]; h[x]=tot;}void add2(int x,int y){ g2[++sum]=y; n2[sum]=h2[x]; h2[x]=sum;}void tarjan(int x){ dfn[x]=low[x]=++euler; s[++top]=x; pd[x]=1; flag[x]=1; int t=h[x]; while (t){ if (!bz[(t+1)/2]&&!zb[(t+1)/2]){ zb[(t+1)/2]=1; if (pd[go[t]]){ if (flag[go[t]]) low[x]=min(low[x],dfn[go[t]]); } else{ tarjan(go[t]); low[x]=min(low[x],low[go[t]]); } } t=next[t]; } if (dfn[x]==low[x]){ num++; do{ belong[s[top]]=num; flag[s[top]]=0; top--; }while (s[top+1]!=x); }} void dfs(int x,int y){ fa[x][0]=y; d[x]=d[y]+1; int t=h2[x]; size[x]=1; while (t){ if (g2[t]!=y){ dfs(g2[t],x); size[x]+=size[g2[t]]; } t=n2[t]; }}void dg(int x,int y){ dfn[x]=++euler; int t=h2[x],j=0; while (t){ if (g2[t]!=y&&(j==0||size[g2[t]]>size[j])) j=g2[t]; t=n2[t]; } if (j){ jump[j]=jump[x]; dg(j,x); } t=h2[x]; while (t){ if (g2[t]!=y&&g2[t]!=j){ jump[g2[t]]=g2[t]; dg(g2[t],x); } t=n2[t]; }}int lca(int x,int y){ if (d[x]<d[y]) swap(x,y); if (d[x]!=d[y]){ int j=floor(log(num)/log(2)); while (j>=0){ if (d[fa[x][j]]>=d[y]) x=fa[x][j]; j--; } } if (x==y) return x; int j=floor(log(num)/log(2)); while (j>=0){ if (fa[x][j]!=fa[y][j]){ x=fa[x][j]; y=fa[y][j]; } j--; } return fa[x][0];}void mark(int p,int l,int r,int v){ tree[p]=(r-l+1)*v; bj[p]=1; set[p]=v;}void down(int p,int l,int r){ int mid=(l+r)/2; if (bj[p]){ mark(p*2,l,mid,set[p]); mark(p*2+1,mid+1,r,set[p]); bj[p]=0; }}void change(int p,int l,int r,int a,int b,int v){ if (l==a&&r==b){ mark(p,l,r,v); return; } down(p,l,r); int mid=(l+r)/2; if (b<=mid) change(p*2,l,mid,a,b,v); else if (a>mid) change(p*2+1,mid+1,r,a,b,v); else{ change(p*2,l,mid,a,mid,v); change(p*2+1,mid+1,r,mid+1,b,v); } tree[p]=tree[p*2]+tree[p*2+1];}int query(int p,int l,int r,int a,int b){ if (l==a&&r==b) return tree[p]; down(p,l,r); int mid=(l+r)/2; if (b<=mid) return query(p*2,l,mid,a,b); else if (a>mid) return query(p*2+1,mid+1,r,a,b); else return query(p*2,l,mid,a,mid)+query(p*2+1,mid+1,r,mid+1,b);}int main(){ freopen("data.in","r",stdin);freopen("data.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,m){ scanf("%d%d",&j,&k); add(j,k); add(k,j); } while (1){ scanf("%d",&q[++cnt][0]); if (q[cnt][0]==-1) break; scanf("%d%d",&q[cnt][1],&q[cnt][2]); if (!q[cnt][0]) bz[(pos[make_pair(q[cnt][1],q[cnt][2])]+1)/2]=1; } cnt--; tarjan(1); fo(i,1,tot) if (!bz[(i+1)/2]&&belong[from[i]]!=belong[go[i]]){ j=belong[from[i]];k=belong[go[i]]; if (j>k) swap(j,k); if (!sop[make_pair(j,k)]){ sop[make_pair(j,k)]=1; add2(j,k); add2(k,j); } } dfs(1,0); fo(j,1,floor(log(num)/log(2))) fo(i,1,num) fa[i][j]=fa[fa[i][j-1]][j-1]; euler=0; dg(1,0); fo(i,2,num) change(1,1,num,dfn[i],dfn[i],1); fd(i,cnt,1){ j=belong[q[i][1]];k=belong[q[i][2]]; if (j==k) continue; l=lca(j,k); if (q[i][0]==0){ while (j!=l){ if (d[jump[j]]<=d[l]){ change(1,1,num,dfn[l]+1,dfn[j],0); j=l; } else{ change(1,1,num,dfn[jump[j]],dfn[j],0); j=fa[jump[j]][0]; } } while (k!=l){ if (d[jump[k]]<=d[l]){ change(1,1,num,dfn[l]+1,dfn[k],0); k=l; } else{ change(1,1,num,dfn[jump[k]],dfn[k],0); k=fa[jump[k]][0]; } } } else{ while (j!=l){ if (d[jump[j]]<=d[l]){ q[i][3]+=query(1,1,num,dfn[l]+1,dfn[j]); j=l; } else{ q[i][3]+=query(1,1,num,dfn[jump[j]],dfn[j]); j=fa[jump[j]][0]; } } while (k!=l){ if (d[jump[k]]<=d[l]){ q[i][3]+=query(1,1,num,dfn[l]+1,dfn[k]); k=l; } else{ q[i][3]+=query(1,1,num,dfn[jump[k]],dfn[k]); k=fa[jump[k]][0]; } } } } fo(i,1,cnt) if (q[i][0]) printf("%d\n",q[i][3]);}
0 0
- 【AHOI2005】【BZOJ1969】LANE 航线规划
- [bzoj1969][AHOI2005]LANE 航线规划
- bzoj1969: [Ahoi2005]LANE 航线规划
- [BZOJ1969][Ahoi2005]LANE 航线规划(树链剖分)
- [BZOJ1969][Ahoi2005]LANE 航线规划(树链剖分+并查集)
- ahoi2005 lane 航线规划
- 洛谷2542 [AHOI2005]航线规划 BZOJ1969
- bzoj 1969: [Ahoi2005]LANE 航线规划
- BZOJ 1969: [Ahoi2005]LANE 航线规划
- BZOJ 线段树 1969: [Ahoi2005]LANE 航线规划
- 【动态缩点】【bzoj 1969】: [Ahoi2005]LANE 航线规划
- [BZOJ]1969: [Ahoi2005]LANE 航线规划 离线树链剖分
- bzoj 1969: [Ahoi2005]LANE 航线规划 离线+树链剖分+线段树
- ahoi2005 lane 航线规划 (60分)——桥的运用
- bzoj 1969: [Ahoi2005]LANE 航线规划(树链剖分+线段树+最小生成树)
- 【BZOJ 1969】【AHOI 2005】LANE 航线规划【离线、hash、并查集、树链剖分、线段树】
- bzoj1969LANE 航线规划
- 航线规划——3103
- vue.js 由浅至深学习宝典
- python map() ,reduce()运用
- 阿里云Ubuntu系统从0搭建LAMP(Apache+MySQL+PHP)以及服务器生产环境常用配置
- 多线程的安全问题
- 公约数公倍数
- [bzoj1969][AHOI2005]LANE 航线规划
- 单链表的C实现及演示
- QUST'S OJ problem1342 完数
- 排序算法之选择排序
- ubuntu下安装docker-compose
- MySQL常见数据类型详解
- java设计模式-观察者模式
- SQL注入攻击
- 键盘hook,dll实现挂载到其他程序