zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    React 使用链表遍历组件树
    React diff 算法
    JavaScript 对象操作
    前端路由hash
    动画运动曲线
    ajax跨域问题
    js版本状态模式
    装饰者模式AOP
    swipe源码循环索引
    组合模式--超级宏命令
  • 原文地址:https://www.cnblogs.com/Narh/p/9700328.html
Copyright © 2011-2022 走看看