航线规划——3103
来源:互联网 发布:手机淘宝宝主页慢 编辑:程序博客网 时间:2024/04/28 07:05
题意:
n个星球,m条边,Q个操作。
(1)破坏一条边;
(2)询问两个星球之间的关键路径的条数(即为一个星球到另一个星球的必经之路)。
数据范围:
30%,n<=100,m<=500,Q<=100;
60%,n<=10000,m<=30000,Q<=20000,数据中没有删边操作;
100%,n<=30000,m<=100000,Q<=40000,数据保证任何时候图都是连通,且没有重边和自环;
思路:
30暴力,这里不多说了;
60就有意思了,操作的题目常常是顺着进行维护难而倒着来操作会简单很多。(正难则反)
倒着来时,就是先将要破坏的边变成加边,即会出现树的形状(不需要解释了…),60分则随机生成这颗树,因为60分没删边。
100其实就多了最小生成树,但这样的话,加边就不单纯了,加边时,当出现环时,那么这就不是关键路径了,所以就要路径压缩一下——并查集。
#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define root 1,n,1#define lson L,mid,p<<1#define rson mid+1,R,p<<1|1#define family tree[p],tree[p<<1],tree[p<<1|1]#define LL long long#define INF 0x3f3f3f3f#define N 100005#define M 200005#define S 19#define W 40005using namespace std;int n,m,mm,q,T;int ans[M];bool vis[N];int Lt[N],Rt[N],dfsList[N],D[N];//dfsint Fa[N],fa[S][N];// PCS lcavector<int>E[M];//dfsset<int>es[M];//add edgestruct Node{ int op,from,to;}A[M],B[M];struct Tree{ struct node{ int L,R,sum; }tree[N<<2]; void build(int L,int R,int p){ tree[p].L=L,tree[p].R=R; if(L==R){ tree[p].sum=D[dfsList[L]]-1;// return; } int mid=(L+R)>>1; build(lson),build(rson); } void update(int L,int R,int p){ if(tree[p].L==L && R==tree[p].R){ tree[p].sum--; return; } int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid)update(L,R,p<<1); else if(L>mid)update(L,R,p<<1|1); else update(lson),update(rson); } int query(int x,int p){ if(tree[p].L==tree[p].R)return tree[p].sum; int mid=(tree[p].L+tree[p].R)>>1; if(x<=mid)return tree[p].sum+query(x,p<<1); else return tree[p].sum+query(x,p<<1|1); }}Tree;struct LCA{ void Up(int &x,int step){ REP(i,0,S-1)if(step&(1<<i))x=fa[i][x]; } int Lca(int a,int b){ if(D[a]>D[b])swap(a,b); Up(b,D[b]-D[a]); if(a==b)return a; DREP(i,S-1,0)if(fa[i][a]!=fa[i][b])a=fa[i][a],b=fa[i][b]; return fa[0][a]; } void Init(){ REP(j,1,S-1) REP(i,1,n) fa[j][i]=fa[j-1][fa[j-1][i]]; }}LCA;struct PCS{ int Find(int x){return Fa[x]==x?x:Fa[x]=Find(Fa[x]);} void Up(int &x){ Tree.update(Lt[x],Rt[x],1); Fa[x]=fa[0][x];x=Find(x);//path compression } void Addedge(int x,int y){ int fx=Find(x),fy=Find(y); while(fx!=fy)Up(D[fx]>D[fy]?fx:fy); } void Init(){ REP(i,1,n)Fa[i]=i; }}PCS;void dfs(int x,int f){ D[x]=D[f]+1; fa[0][x]=f; Lt[x]=++T; dfsList[T]=x; vis[x]=1; REP(i,0,E[x].size()-1){ int y=E[x][i]; if(y==f || es[x].find(y)!=es[x].end())continue; if(vis[y]){B[++mm].from=x,B[mm].to=y;continue;} // find link dfs(y,x); } Rt[x]=T;}void Rd(){ scanf("%d%d%d",&n,&m,&q); REP(i,1,m){ int a,b; scanf("%d%d",&a,&b); E[a].push_back(b); E[b].push_back(a); } REP(i,1,q){ scanf("%d%d%d",&A[i].op,&A[i].from,&A[i].to); if(!A[i].op)es[A[i].from].insert(A[i].to),es[A[i].to].insert(A[i].from); }}void solve(){ dfs(1,0); LCA.Init(); PCS.Init(); Tree.build(root); REP(i,1,mm)PCS.Addedge(B[i].from,B[i].to); DREP(i,q,1){ if(!A[i].op)PCS.Addedge(A[i].from,A[i].to);// add edge else ans[i]=Tree.query(Lt[A[i].from],1)+Tree.query(Lt[A[i].to],1)-2*Tree.query(Lt[LCA.Lca(A[i].from,A[i].to)],1); }}void Pr(){ REP(i,1,q)if(A[i].op)printf("%d\n",ans[i]);}int main(){ Rd(); solve(); Pr(); return 0;}
小结:
dfs序->找到符合线段树的一种排列
线段树查询+修改
倍增求lca,并查集加边。
阅读全文
0 0
- 航线规划——3103
- ahoi2005 lane 航线规划 (60分)——桥的运用
- ahoi2005 lane 航线规划
- bzoj1969LANE 航线规划
- 【AHOI2005】【BZOJ1969】LANE 航线规划
- [bzoj1969][AHOI2005]LANE 航线规划
- bzoj1969: [Ahoi2005]LANE 航线规划
- 楚楚街笔试题—航线
- 动态规划解决航线设置问题
- bzoj 1969: [Ahoi2005]LANE 航线规划
- [BZOJ1969][Ahoi2005]LANE 航线规划(树链剖分)
- 洛谷2542 [AHOI2005]航线规划 BZOJ1969
- 航线规划(离线+路径压缩)
- BZOJ 1969: [Ahoi2005]LANE 航线规划
- BZOJ 线段树 1969: [Ahoi2005]LANE 航线规划
- 【动态缩点】【bzoj 1969】: [Ahoi2005]LANE 航线规划
- Codevs5288 航线设计(动态规划加强版) 解题报告
- [BZOJ1969][Ahoi2005]LANE 航线规划(树链剖分+并查集)
- Linux的sort命令
- IDEA入门级使用教程
- c语言中关于一维数组的指针访问
- 双硬盘下安装centos关于开机引导的问题
- Java 类加载机制详解
- 航线规划——3103
- shell命令替换
- php封装一个链接数据库的函数(增删改查)
- Java/大数据常见面试
- SparkStreaming 性能调优
- IT人物——冯诺依曼
- 【python tutorial 3.6】阅读笔记--【6.模块】
- Android Intent Flag实现singleTask模式
- 使类和成员的可访问性最小化。