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));    }}
原创粉丝点击