LOJ #2876. 「JOISC 2014 Day2」水壶 BFS+最小生成树+倍增LCA

非常好的一道图论问题.  

显然,我们要求城市间的最小生成树,然后查询路径最大值.    

然后我们有一个非常神的处理方法:进行多源 BFS,处理出每一个城市的管辖范围.     

显然,如果两个城市的管辖范围没有交集的话连边一定不是优秀的(一定会有一种都在管辖范围之内的连边方式来代替这种连边方式)   

然后由于每一个点只属于一个城市的管辖范围,所以每个点只会扩展一次,这个 BFS 的复杂度是线性的. 

code:

#include <bits/stdc++.h>  
#define N 2006  
#define M 200005 
#define ll long long   
using namespace std; 
namespace IO {  
    void setIO(string s) {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        // freopen(out.c_str(),"w",stdout);  
    }
};      
char str[N];
int n,m,P,Q,edges; 
int dep[M]; 
int hd[M],to[M<<1],nex[M<<1],val[M<<1],vis[M],fa[18][M],Max[18][M];       
int wall[N][N],id[N][N],dis[N][N],bel[N][N],p[N*N];     
int dx[]={-1,0,1,0};   
int dy[]={0,1,0,-1};   
struct node { 
    int x,y; 
    node(int x=0,int y=0):x(x),y(y){}   
};   
struct edge {
    int x,y; 
    edge(int x=0,int y=0):x(x),y(y){}  
};   
queue<node>q;   
vector<edge>G[N*N];        
void add(int u,int v,int c) {
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;  
}         
void init() {
    for(int i=0;i<N*N;++i) p[i]=i;  
}
int find(int x) {
    return p[x]==x?x:p[x]=find(p[x]);  
}
int merge(int x,int y) {
    x=find(x); 
    y=find(y);   
    if(x==y) 
        return 0;    
    p[x]=y;  
    return 1;   
}
void dfs(int x,int ff) {
    vis[x]=1;
    fa[0][x]=ff; 
    dep[x]=dep[ff]+1;     
    for(int i=1;i<18;++i) 
        fa[i][x]=fa[i-1][fa[i-1][x]];   
    for(int i=1;i<18;++i) 
        Max[i][x]=max(Max[i-1][fa[i-1][x]],Max[i-1][x]);  
    for(int i=hd[x];i;i=nex[i]) { 
        int v=to[i];   
        if(v!=ff) 
            Max[0][v]=val[i],dfs(v,x);       
    }  
}
int query(int x,int y) { 
    int ma=0,i,j;    
    if(dep[x]!=dep[y]) {
        if(dep[y]<dep[x]) swap(x,y);     
        for(i=17;i>=0;--i) {                                                                       
            if(dep[fa[i][y]]>=dep[x]) {
                ma=max(ma,Max[i][y]);    
                y=fa[i][y];       
            }
        }
    }
    if(x==y) return ma;      
    for(i=17;i>=0;--i) {
        if(fa[i][y]!=fa[i][x]) {
            ma=max(ma,max(Max[i][y],Max[i][x]));   
            x=fa[i][x],y=fa[i][y];   
        }  
    }
    return max(ma,max(Max[0][y],Max[0][x]));    
}
int main() { 
    // IO::setIO("input");  
    int i,j,idx=0;   
    scanf("%d%d%d%d",&n,&m,&P,&Q);     
    for(i=1;i<=n;++i) { 
        scanf("%s",str+1);   
        for(j=1;j<=m;++j) {   
            id[i][j]=++idx;               
            wall[i][j]=(str[j]=='#');    
        }
    }                 
    for(i=1;i<=P;++i) {
        int x,y; 
        scanf("%d%d",&x,&y);   
        bel[x][y]=i;         
        q.push(node(x,y));   
    }     
    while(!q.empty()) {
        node e=q.front(); q.pop();  
        int x=e.x,y=e.y;      
        for(i=0;i<4;++i) {
            int X=x+dx[i],Y=y+dy[i];      
            if(id[X][Y]&&!wall[X][Y]) {         
                if(!bel[X][Y]) {
                    bel[X][Y]=bel[x][y];  
                    dis[X][Y]=dis[x][y]+1; 
                    q.push(node(X,Y));   
                }
                else if(bel[X][Y]!=bel[x][y]){    
                    G[dis[X][Y]+dis[x][y]].push_back(edge(bel[X][Y],bel[x][y]));   
                }
            }
        }
    }      
    init();   
    for(i=0;i<N*N;++i) {
        for(j=0;j<G[i].size();++j) {
            int u=G[i][j].x,v=G[i][j].y;       
            if(merge(u,v)) { 
                add(u,v,i);   
                add(v,u,i);   
            }
        }
    }   
    for(i=1;i<=P;++i) {
        if(!vis[i]) {
            dfs(i,0);   
        }
    }
    for(i=1;i<=Q;++i) {
        int x,y; 
        scanf("%d%d",&x,&y);    
        if(find(x)!=find(y)) 
            printf("-1
");  
        else 
            printf("%d
",query(x,y));   
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12375731.html