zoukankan      html  css  js  c++  java
  • 棋盘上的守卫 并查集模拟外向基环树

    棋盘上的守卫

    基环树就是n个点n条边的树,每个点的入度为1就是外向基环树因为这样的话这个图是往外扩张的,反之内向。

    然后这个树自然就只且只有一个环。

    题意:n行m列,要求选n个守卫守卫n个行,m个守卫守卫m个列,守卫不能重复,且每个守卫只能守卫行或列,每个守卫一个价值,求最小的代价。

    思路:将关于点的图转化为关于边的图,构造一个图含有n+m个点表示n行和m列,题目给的图上的每个点的价值就可以代表点到点的边权了,可以想到如果要覆盖所有的点,就是满足条件的方案,这样的话这个图就是一个每个点都是入度为1的基环树,然后可以给边从小到大排个序,通过并查集模拟生成一个代价最小的外向基环树就行了。对于基环树,可以发现不在乎一个边所指的方向,只要选的边所产生的点集构成的环满足只有一个就好了,所以只需要并查集判断点所在的集合,开个huan[]用来判断一个点所在的集合是否产生了环,合并时对huan取并集就可以了。也可能一个,而是几个独立的基环树

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn=1e5+10;
    int fa[2*maxn];
    struct note
    {
        int x,y,z;
    } e[2*maxn];
    int cmp(note a,note b)
    {
        return a.z<b.z;
    }
    int huan[2*maxn];
    int getf(int x)
    {
        return fa[x]=fa[x]==x?x:getf(fa[x]);
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int cnt=0;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                int t;
                scanf("%d",&t);
                note tt;
                tt.x=i+m;
                tt.y=j;
                tt.z=t;
                e[++cnt]=tt;
            }
        for(int i=1; i<=n+m; i++)
            fa[i]=i;
        sort(e+1,e+1+cnt,cmp);
        ll ans=0;
        for(int i=1; i<=cnt; i++)
        {
            int x,y,z;
            x=e[i].x;
            y=e[i].y;
            z=e[i].z;
            int t1,t2;
            t1=getf(x);
            t2=getf(y);
            if(t1!=t2&&(huan[t1]==0||huan[t2]==0))
            {
                fa[t2]=t1; // 这里注意一下:是将t2放到了t1的圈子里,下面才有t1去和t2取并集 
                huan[t1]|=huan[t2];
                ans=ans+z;
            }
            if(t1==t2&&huan[t1]==0)
            {
                ans=ans+z;
                huan[t1]=1;
            }
        }
        printf("%lld",ans);
    }
  • 相关阅读:
    HDU 4619 Warm up 2 (多校)
    深入浅出Node.js (9)
    HDU 1106 排序(排序)
    字符串相关心得
    HDU 2547 无剑无我(数学)
    HDU 2549 壮志难酬(字符串,处理小数点)
    HDU 2551 竹青遍野(循环,水)
    HDU 2552 三足鼎立(数学函数)
    HDU 2555 陷阱(模拟,结构体数组)
    HDU 2561 第二小整数(排序,水)
  • 原文地址:https://www.cnblogs.com/dongdong25800/p/11266579.html
Copyright © 2011-2022 走看看