zoukankan      html  css  js  c++  java
  • P1661 扩散

    P1661 扩散

    二分+最小生成树(kruskal使用并查集)

    不清楚的题意导致我被坑了qwq,其实间接联通也是允许的。所以可以使用并查集+最小生成树维护

    每次二分答案,然后跑一遍最小生成树判断是否联通。

    end.

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    struct edge{
        int from,to,dis;
    }a[2502];
    int n,cnt,x[52],y[52],fa[52];
    inline int find(int x) {return fa[x]==x ? fa[x]:fa[x]=find(fa[x]);} //路径压缩
    inline void uni(int x,int y){
        int r1=find(fa[x]),r2=find(fa[y]);
        if(r1!=r2) fa[r1]=r2;
    }//并查集基本操作:find,uni。一个找父亲,一个连父亲
    inline bool cmp(const edge &A,const edge &B) {return A.dis<B.dis;}
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]);
        for(int i=1;i<n;++i)
            for(int j=i+1;j<=n;++j)
                a[++cnt]=(edge){i,j,abs(x[i]-x[j])+abs(y[i]-y[j])};//曼哈顿距离计算
        sort(a+1,a+cnt+1,cmp); //按权值升序排
        int l=0,r=1e9,mid,k;
        while(l<r){
            mid=l+((r-l)>>1); k=0; 
            for(int i=1;i<=n;++i) fa[i]=i; //重置父亲
            for(int i=1;i<=cnt;++i){
                if(a[i].dis>(mid<<1)) break; //注意两个点都在扩展,所以要*2
                if(find(a[i].from)!=find(a[i].to)) uni(a[i].from,a[i].to),++k;
                if(k==n-1) break; //剪枝
            }//kruskal最小生成树
            if(k!=n-1) l=mid+1; //不符合条件
            else r=mid; 
        }
        printf("%d",l);
        return 0;
    }
  • 相关阅读:
    vue eslint报错解决办法
    vue动态修改title
    vue组件引入失败原因之一
    BootStrap 获得轮播中的索引和当前活动的焦点对象
    云开发创建云函数
    vue-cli打包后,图片路径不对
    vue打包完样式冲突
    css文字环绕
    Java——Netty Reactor模型(转)
    Java——Netty 线程模型与Reactor 模式(转)
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9571903.html
Copyright © 2011-2022 走看看