• BZOJ4883 棋盘上的守卫(环套树+最小生成树)


      容易想到网络流之类的东西,虽然范围看起来不太可做,不过这提供了一种想法,即将行列分别看做点。那么我们需要找一种连n+m条边的方案,使得可以从每条边中选一个点以覆盖所有点。显然每个点至少要连一条边。于是这个东西就必须是环套树森林了,并且显然其可以满足条件。现在要求的就是最小环套树森林。

      求法类似kruskal,只要连了这条边之后该连通块的边数<=点数就给他连上。显然这样得到的是环套树森林,至于为什么最小,证明方法也与kruskal类似,即如果当前边不冗余却不加,则需要另一条边来做等效(这里等效比较广义,比如树边可以与其端点连通块的环边等效)的事,而贪心过程说明不存在更小的这样的边了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 100010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,t,fa[N],size[N],cnt[N];
    ll ans;
    struct data
    {
        int x,y,z;
        bool operator <(const data&a) const
        {
            return z<a.z;
        }
    }edge[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4883.in","r",stdin);
        freopen("bzoj4883.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            t++,edge[t].x=i,edge[t].y=n+j,edge[t].z=read();
        sort(edge+1,edge+n*m+1);
        for (int i=1;i<=n+m;i++) fa[i]=i,size[i]=1,cnt[i]=0;
        for (int i=1;i<=n*m;i++)
        {
            int x=find(edge[i].x),y=find(edge[i].y);
            if (x!=y)
            {
                if (cnt[x]+cnt[y]+1<=size[x]+size[y])
                ans+=edge[i].z,fa[x]=y,size[y]+=size[x],cnt[y]+=cnt[x]+1;
            }
            else if (cnt[x]<size[x]) ans+=edge[i].z,cnt[x]++;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    PHP Laravel Install and Quickstart
    PHP Composer
    PHP学习 Cookie和Session
    PHP学习 Object Oriented 面向对象 OO
    PHP学习 例外和错误处理
    PHP学习 文件访问和写入
    PHP学习 函数 function
    PHP学习 流程控制和数组
    修改docker镜像地址为阿里云
    通信对象 System.ServiceModel.Channels.ServiceChannel 无法用于通信,因为其处于“出错”状态
  • 原文地址:https://www.cnblogs.com/Gloid/p/10028783.html
Copyright © 2020-2023  润新知