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\n");  
        else 
            printf("%d\n",query(x,y));   
    }
    return 0;
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值