bzoj 4242: 水壶 最小生成树&树上倍增
来源:互联网 发布:大s性格 知乎 编辑:程序博客网 时间:2024/04/28 07:09
为了降低AC率这道题目我各种花样作死爆OJ,最后还是和标算改得差不多了。。。
显然答案应该为建筑物构成的最小生成树中,两点间的最大路径;那么只要得到这棵最小生成树就可以用倍增在O(QlogN)的时间内得到答案了。因此关键是求最小生成树。
注意到是平面图,因此考虑用bfs求最小生成树。直接以每个建筑为原点拓展显然不行,那么我们可以把每个建筑都加入队列一起拓展,那么对于一个点,一定会被其中的一个建筑第一次拓展到,则令这个点为该建筑的“势力范围”。那么对于两个建筑“势力范围”边界上接触的点,显然这两个建筑之间的边只能有边界上的点得到。因此就用这些点连边即可。显然这样得到是最小生成树。
然后用倍增求lca的方法得到答案即可。
AC代码如下:
#include<iostream>#include<cstdio>#include<cstring>#define N 2005#define M 200005using namespace std;int n,m,pt,cas,tot,cnt,fa[M][18],g[M][18],bin[25],anc[M],fst[M],pnt[N*N],nxt[N*N],len[N*N];int dep[M],h[N*N][2],d[N][N],blg[N][N]; bool mp[N][N];const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};int read(){int x=0; char ch=getchar();while (ch<'0' || ch>'9') ch=getchar();while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }return x;}struct grapg{int fst[N*N];void add(int x,int y,int z){pnt[++tot]=y; nxt[tot]=fst[x]; len[tot]=z; fst[x]=tot;}}g1,g2;int getanc(int x){ return (x==anc[x])?x:anc[x]=getanc(anc[x]); }void dfs(int x){int p,i;for (i=1; bin[i]<=dep[x]; i++){fa[x][i]=fa[fa[x][i-1]][i-1];g[x][i]=max(g[x][i-1],g[fa[x][i-1]][i-1]);}for (p=g2.fst[x]; p; p=nxt[p]){int y=pnt[p];if (y!=fa[x][0]){fa[y][0]=x; g[y][0]=len[p];dep[y]=dep[x]+1; dfs(y);}}}int qry(int x,int y){if (getanc(x)!=getanc(y)) return -1;if (dep[x]<dep[y]) swap(x,y); int tmp=dep[x]-dep[y],i,ans=0;for (i=0; bin[i]<=tmp; i++)if (tmp&bin[i]){ ans=max(ans,g[x][i]); x=fa[x][i]; }for (i=17; i>=0; i--)if (fa[x][i]!=fa[y][i]){ans=max(ans,max(g[x][i],g[y][i]));x=fa[x][i]; y=fa[y][i];}if (x!=y) ans=max(ans,max(g[x][0],g[y][0])); return ans;}int main(){m=read(); n=read(); pt=read(); cas=read();int i,j; char ch=getchar();bin[0]=1; for (i=1; i<=18; i++) bin[i]=bin[i-1]<<1;for (i=1; i<=m; i++){while (ch!='.' && ch!='#') ch=getchar();for (j=1; j<=n; j++,ch=getchar())mp[i][j]=(ch=='.');}int head=0,tail=0,x,y,z;memset(d,-1,sizeof(d));for (i=1; i<=pt; i++){h[++tail][0]=x=read(); h[tail][1]=y=read();blg[x][y]=i; d[x][y]=0;anc[i]=i;}while (head<tail){x=h[++head][0]; y=h[head][1]; z=blg[x][y];for (i=0; i<4; i++){int u=x+dx[i],v=y+dy[i];if (u>0 && u<=m && v>0 && v<=n && mp[u][v])if (d[u][v]==-1){d[u][v]=d[x][y]+1; blg[u][v]=z;h[++tail][0]=u; h[tail][1]=v;} else if (z!=blg[u][v]) g1.add(d[u][v]+d[x][y],z,blg[u][v]);}}for (i=0; i<m*n; i++)for (j=g1.fst[i]; j; j=nxt[j]){x=getanc(pnt[j]); y=getanc(len[j]);if (x!=y){anc[x]=y; g2.add(pnt[j],len[j],i);g2.add(len[j],pnt[j],i);}}for (i=1; i<=pt; i++)if (getanc(i)==i){dep[i]=1; dfs(i);}while (cas--) printf("%d\n",qry(read(),read()));return 0;}
by lych
2016.3.26
0 1
- bzoj 4242: 水壶 最小生成树&树上倍增
- [网格最小生成树] BZOJ 4242 水壶
- [bzoj4242][最小生成树]水壶
- [BZOJ]1977 次小生成树 树上倍增
- bzoj3732 Network 最小生成树+LCA+树上倍增
- NOIP2017模拟 玩游戏 最小生成树 树上倍增
- [最小生成树] [LCA] [BZOJ4242] 水壶(bottle)
- 【BZOJ】【P3732】【Network】【题解】【最小生成树+倍增】
- BZOJ 4144: [AMPPZ2014]Petrol 最短路+最小生成树+倍增
- bzoj 4144 [AMPPZ2014]Petrol 最短路+最小生成树+倍增
- BZOJ 3732: Network(最小生成树+倍增)
- BZOJ 3732 Network —— 最小生成树 + 倍增LCA
- BZOJ-1977 次小生成树 Tree 树上倍增LCA+Kruskal+位运算
- 【bzoj1977】【次小生成树】【树上倍增】
- BZOJ 4242 水壶
- bzoj 4242: 水壶
- bzoj3732 -- 最小生成树+倍增
- bzoj 1977: [BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
- Web前端应该从哪些方面来优化网站
- 第四周上机实践项目 项目5--用递归方法求解(2)
- ElasticSearch中根据查询结果删除数据(delete by query)
- java中多态的经典问题分析
- lua面向对象学习
- bzoj 4242: 水壶 最小生成树&树上倍增
- Tomcat热部署
- shell编程实践1
- 关于BufferedInputStream和FileInputStream的区别
- 一步步点亮LED1_硬件工作原理及原理图查阅
- 深入线程:生产者与消费者问题
- zjut1633——好简单的动态规划
- IOS平台ASI框架 和 AFN框架 之Https通讯
- hdoj--田忌赛马后传(贪心)