bzoj 4242: 水壶
来源:互联网 发布:word文档数据恢复 编辑:程序博客网 时间:2024/05/17 06:08
题意:
给出一些平面上的点,两两间的距离为最短路。求两点间的路径中最大值的最小值。
题解:
容易想到,就是最小生成树上的路径的最大值。
关键怎么用各种奇技淫巧求这个最小生成树呢?
orz题解
那么每个点最多有四个区域重合,即建四条边。
然后就是普通的MST+倍增。 就这么一道题做+调了一下午+一晚上是不是很菜
code:
#include<queue>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct node{ int x,y,c,next;}b[200010],e[20000010],a[800010];int Len=0,len=0,last[200010];struct trnode{ int dep,fa[25],max[25]; bool vis; trnode(){vis=false;}}tr[200010];queue<pair<int,int> > q;int yh[7]={-1,0,1,0};int yl[7]={0,1,0,-1};int n,m,p,Q;int bel[2010][2010],dis[2010][2010];int map[2010][2010],fa[200010];int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void insert(int x,int y,int c){e[++Len].x=x;e[Len].y=y;e[Len].c=c;}bool cmp(node a,node b){return a.c<b.c;}void ins(int x,int y,int c){ a[++len].y=y;a[len].c=c; a[len].next=last[x];last[x]=len;}int findfa(int x){ if(fa[x]!=x) fa[x]=findfa(fa[x]); return fa[x];}void dfs(int x,int fa,int c){ tr[x].dep=tr[fa].dep+1;tr[x].fa[0]=fa;tr[x].max[0]=c; tr[x].vis=true; for(int i=1;(1<<i)<=tr[x].dep;i++) { tr[x].fa[i]=tr[tr[x].fa[i-1]].fa[i-1]; tr[x].max[i]=max(tr[tr[x].fa[i-1]].max[i-1],tr[x].max[i-1]); } for(int i=last[x];i;i=a[i].next) { int y=a[i].y; if(y==fa) continue; dfs(y,x,a[i].c); }}int solve(int x,int y){ int tx=findfa(x),ty=findfa(y); if(tx!=ty) return -1; if(tr[x].dep<tr[y].dep) swap(x,y); int ans=0; for(int i=19;i>=0;i--) if((1<<i)<=tr[x].dep-tr[y].dep) ans=max(ans,tr[x].max[i]),x=tr[x].fa[i]; if(x==y) return ans; for(int i=19;i>=0;i--) if((1<<i)<=tr[x].dep&&tr[x].fa[i]!=tr[y].fa[i]) { ans=max(ans,tr[x].max[i]); ans=max(ans,tr[y].max[i]); x=tr[x].fa[i];y=tr[y].fa[i]; } ans=max(ans,tr[x].max[0]); ans=max(ans,tr[y].max[0]); return ans;}int main(){ scanf("%d %d %d %d",&n,&m,&p,&Q); memset(map,-1,sizeof(map)); for (int i=1;i<=n;i++) { char ch; while (ch!='.' && ch!='#') ch=getchar(); for (int j=1;j<=m;j++,ch=getchar()) map[i][j]=(ch=='.')?0:-1; } memset(dis,-1,sizeof(dis)); for(int i=1;i<=p;i++) { b[i].x=read();b[i].y=read(); int x=b[i].x,y=b[i].y; bel[x][y]=i;dis[x][y]=0; q.push(make_pair(x,y)); } while(!q.empty()) { int x=q.front().first,y=q.front().second;q.pop(); int t=bel[x][y]; for(int i=0;i<4;i++) { int tx=x+yh[i],ty=y+yl[i]; if(map[tx][ty]==-1) continue; if(bel[tx][ty]==0) { bel[tx][ty]=t; dis[tx][ty]=dis[x][y]+1; q.push(make_pair(tx,ty)); } else if(bel[tx][ty]!=bel[x][y]) insert(bel[tx][ty],t,dis[tx][ty]+dis[x][y]); } } sort(e+1,e+Len+1,cmp); for(int i=1;i<=p;i++) fa[i]=i; for(int i=1;i<=Len;i++) { int x=e[i].x,y=e[i].y,tx=findfa(x),ty=findfa(y); if(tx!=ty) fa[tx]=ty,ins(x,y,e[i].c),ins(y,x,e[i].c); } tr[0].dep=-1; for(int i=1;i<=p;i++) if(!tr[i].vis) dfs(i,0,0); while(Q--) { int S,T;S=read();T=read(); printf("%d\n",solve(S,T)); }}
阅读全文
1 0
- BZOJ 4242 水壶
- bzoj 4242: 水壶
- [网格最小生成树] BZOJ 4242 水壶
- 4242: 水壶
- bzoj 4242: 水壶 最小生成树&树上倍增
- 水壶
- bzoj4242: 水壶
- 水壶再一次爆了!!!
- 水壶、茶叶罐和我
- uva571 - Jugs(水壶)
- 用类去封装花瓶,水壶,对象
- 闷水壶的冒险码头
- POJ 3414 Pots(水壶)
- [bzoj4242][最小生成树]水壶
- <算法导论>第八章4 水壶(Kettle)
- 去除热水壶里的污垢
- 算法进化历程之“水壶问题”
- 满满一水壶的寻常事
- 百科知识 .tar.xz文件如何打开
- 百科知识 epub文件如何打开
- 图论训练 重量差异 [并查集]
- 百科知识 DCR文件如何打开
- 百科知识 ass文件如何打开
- bzoj 4242: 水壶
- 百科知识 isz文件如何打开
- 百科知识 kux文件如何打开
- 百科知识 STEP文件如何打开
- mysql查询优化
- 百科知识 tar文件如何打开
- 百科知识 scm文件如何打开
- 百科知识 hta文件如何打开
- 百科知识 华为手机P7如何更换电池