bzoj4242: 水壶

来源:互联网 发布:最全合理网络理财产品 编辑:程序博客网 时间:2024/05/17 08:25

码了一上午,真是菜啊。
每个建筑都有一块占领区域,当两块区域相连,对两个建筑连长度为建筑到这个点到另一个建筑距离的边,求一遍最小生成树,之后每个询问就求倍增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;}
原创粉丝点击