• bzoj 4883 [Lydsy1705月赛]棋盘上的守卫——并查集(思路!)


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4883

    把各行和各列看成n+m个点。

    如果一下能防守行和列,就是最大匹配了。这是每两个左右部点需要一条边。

    现在一行和一列都需要专门防守,其实可以看成每个点都需要一条边!

    记录并查集内部已经有没有环,在连边的讨论一下即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    int n,m,xnt,fa[N];
    ll ans;
    bool fx[N];
    struct Ed{
        int x,y,w;
        Ed(int x=0,int y=0,int w=0):x(x),y(y),w(w) {}
        bool operator< (const Ed &b) const
            {return w<b.w;}
    }ed[N];
    int rdn()
    {
        int ret=0;bool fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return fx?ret:-ret;
    }
    void add(int x,int y,int z)
    {
        ed[++xnt]=Ed(x,y,z);
    }
    int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
    int main()
    {
        n=rdn(); m=rdn();
        for(int i=1;i<=n;i++)
            for(int j=1,w;j<=m;j++)
            {
                w=rdn();
                add(i,j+n,w);
            }
        int d=n+m;
        for(int i=1;i<=d;i++) fa[i]=i;
        sort(ed+1,ed+xnt+1);
        for(int i=1,u,v;i<=xnt;i++)
        {
            u=find(ed[i].x); v=find(ed[i].y);
            if(u!=v&&(fx[u]&fx[v])==0)
            {
                fa[u]=v; fx[v]|=fx[u]; ans+=ed[i].w;
            }
            else if(u==v&&!fx[u])
            {
                fx[u]=1; ans+=ed[i].w;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    sql server 查询当前月份日期列表数据
    redis + cookies 实现持久登入
    JS浏览器兼容问题
    Multicast注册中心
    django模板高级进阶
    django高级视图和URL配置
    django表单操作之django.forms
    django站点管理
    django表单
    django数据库模型
  • 原文地址:https://www.cnblogs.com/Narh/p/9700328.html
Copyright © 2020-2023  润新知