bzoj4242: 水壶
来源:互联网 发布:最全合理网络理财产品 编辑:程序博客网 时间:2024/06/08 13:16
码了一上午,真是菜啊。
每个建筑都有一块占领区域,当两块区域相连,对两个建筑连长度为建筑到这个点到另一个建筑距离的边,求一遍最小生成树,之后每个询问就求倍增lca维护边权最大值就可以了。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<vector>using namespace std;queue<int> q1;queue<int> q2;int read(){ char ch=getchar();int f=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();} return f;}int fa[200005],head[200005],dep[200005],anc[200005][19],tot,cnt,root,ans[200005][19];struct node{ int from; int to; int next; int w;}edge[400005],e[4000005];int a[2005][2005],dis[2005][2005],n,m,p,q,num,now_color;char s[2005];int color[200005];int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]);}void ins(int u,int v,int w){ e[++tot].from=u; e[tot].to=v; e[tot].w=w; e[tot].w=w;}void add(int u,int v,int w){ edge[cnt].from=u; edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;}int cmp(node x,node y){ return x.w<y.w;}void bfs(){ while(!q1.empty()) { int x=q1.front(),y=q2.front(); q1.pop();q2.pop(); if(a[x+1][y]!=-1) { if(a[x+1][y]==0) { dis[x+1][y]=dis[x][y]+1; a[x+1][y]=a[x][y]; q1.push(x+1); q2.push(y); } else if(a[x][y]!=a[x+1][y]) { ins(a[x][y],a[x+1][y],dis[x][y]+dis[x+1][y]+1); } } if(a[x][y+1]!=-1) { if(a[x][y+1]==0) { dis[x][y+1]=dis[x][y]+1; a[x][y+1]=a[x][y]; q1.push(x); q2.push(y+1); } else if(a[x][y]!=a[x][y+1]) { ins(a[x][y],a[x][y+1],dis[x][y]+dis[x][y+1]+1); } } if(a[x-1][y]!=-1) { if(a[x-1][y]==0) { dis[x-1][y]=dis[x][y]+1; a[x-1][y]=a[x][y]; q1.push(x-1); q2.push(y); } else if(a[x][y]!=a[x-1][y]) { ins(a[x][y],a[x-1][y],dis[x][y]+dis[x-1][y]+1); } } if(a[x][y-1]!=-1) { if(a[x][y-1]==0) { dis[x][y-1]=dis[x][y]+1; a[x][y-1]=a[x][y]; q1.push(x); q2.push(y-1); } else if(a[x][y]!=a[x][y-1]) { ins(a[x][y],a[x][y-1],dis[x][y]+dis[x][y-1]+1); } } }}void dfs(int x){ color[x]=now_color; for(int i=1;i<=18;i++) { if(dep[x]>(1<<i)) { anc[x][i]=anc[anc[x][i-1]][i-1]; ans[x][i]=max(ans[x][i-1],ans[anc[x][i-1]][i-1]); } else break; } for(int i=head[x];i!=-1;i=edge[i].next) { if(anc[x][0]!=edge[i].to) { anc[edge[i].to][0]=x; ans[edge[i].to][0]=edge[i].w; dep[edge[i].to]=dep[x]+1; dfs(edge[i].to); } }}int lca(int x,int y){ int ss=0; if(dep[x]<dep[y]) swap(x,y); int d=dep[x]-dep[y]; for(int i=18;i>=0;i--) { if(d&(1<<i)) { ss=max(ss,ans[x][i]); x=anc[x][i]; } } if(x==y) return ss; for(int i=18;i>=0;i--) { if(anc[x][i]!=anc[y][i]) { ss=max(ss,ans[x][i]); ss=max(ss,ans[y][i]); x=anc[x][i]; y=anc[y][i]; } } if(anc[x][0]) { ss=max(ss,ans[x][0]); ss=max(ss,ans[y][0]); } return ss;}int main(){ memset(a,-1,sizeof(a)); memset(head,-1,sizeof(head)); n=read(),m=read(),p=read(),q=read(); for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=m;j++) { if(s[j]=='#') a[i][j]=-1; else a[i][j]=0; } } for(int i=1;i<=p;i++) { int x=read(),y=read(); a[x][y]=i; q1.push(x); q2.push(y); } bfs(); sort(e+1,e+tot+1,cmp);; for(int i=1;i<=p;i++) fa[i]=i; for(int i=1;i<=tot;i++) { int x=find(e[i].from),y=find(e[i].to); if(x!=y) { add(e[i].from,e[i].to,e[i].w); add(e[i].to,e[i].from,e[i].w); fa[x]=y; num++; if(num==p-1) break; } } for(int i=1;i<=p;i++) { if(!color[i]) { now_color++; dep[i]=1; dfs(i); } } for(int i=1;i<=q;i++) { int x=read(),y=read(); if(color[x]!=color[y]) puts("-1"); else printf("%d\n",lca(x,y)-1); } return 0;}
阅读全文
0 0
- bzoj4242: 水壶
- [bzoj4242][最小生成树]水壶
- [最小生成树] [LCA] [BZOJ4242] 水壶(bottle)
- 水壶
- 4242: 水壶
- 水壶再一次爆了!!!
- 水壶、茶叶罐和我
- uva571 - Jugs(水壶)
- BZOJ 4242 水壶
- bzoj 4242: 水壶
- 用类去封装花瓶,水壶,对象
- 闷水壶的冒险码头
- POJ 3414 Pots(水壶)
- <算法导论>第八章4 水壶(Kettle)
- 去除热水壶里的污垢
- 算法进化历程之“水壶问题”
- 满满一水壶的寻常事
- 数据迁移工具--“水壶”(一)
- mysql在linux下表名大小写以及mysql最大连接数
- 腾讯2016秋招题目
- 百度地图 添加云检索数据
- 引入script jsp文件就报错 Uncaught SyntaxError: Unexpected token <
- many-to-many 多对多关联
- bzoj4242: 水壶
- redis 命令
- Failed to contact Jack server Try 'jack-diagnose'
- Java并发编程学习记录#1
- 数组概述-数组去重-string
- 每天一个linux命令目录
- spring boot整合rabbitmq踩坑
- HttpClient通过Post上传文件
- 大数据经典学习路线(及供参考)