第三章 图论 No.11二分图,匈牙利算法与点覆盖

这篇具有很好参考价值的文章主要介绍了第三章 图论 No.11二分图,匈牙利算法与点覆盖。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

二分+染色:257. 关押罪犯

257. 关押罪犯 - AcWing题库
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

最大最小问题,一眼二分
答案的范围在 [ 1 , 1 e 9 ] [1, 1e9] [1,1e9]之间,二分答案,check(mid)
check:将所有权值大于mid的边进行二分,若能得到二分图,返回true,否则返回false
最终将得到最优解ans,所有大于ans的边组成的图为二分图,若是图中有边的权值小于ans,那么这个图就不是二分图
当ans为0时,说明原图就是一张二分图,此时的答案也为0,不需要特判,所以二分的区间为 [ 0 , 1 e 9 ] [0, 1e9] [0,1e9]

#include <iostream>
#include <cstring>
using namespace std;

const int N = 20010, M = 2e5 + 10;
int h[N], e[M], ne[M], w[M], idx;
int color[N];
int n, m;

void add(int x, int y, int d)
{
    e[idx] = y, ne[idx] = h[x], w[idx] = d, h[x] = idx ++ ;
}

bool dfs(int x, int c, int mid)
{
    color[x] = c;
    for (int i = h[x]; i != -1; i = ne[i])
    {
        if (w[i] <= mid) continue;
        int y = e[i];
        if (!color[y])
        {
            if (!dfs(y, 3 - c, mid)) return false;
        }
        else if (color[y] == c) return false;
    }
    return true;
}

bool check(int mid)
{
    memset(color, 0, sizeof(color));
    for (int i = 1; i <= n; ++ i )
        if (!color[i])
            if (!dfs(i, 1, mid))
                return false;
                
    return true;
}

int main()
{
    memset(h, -1, sizeof(h));
    scanf("%d%d", &n, &m);
    int x, y, d;
    for (int i = 0; i < m; ++ i )
    {
        scanf("%d%d%d", &x, &y, &d);
        add(x, y, d), add(y, x, d);
    }
    
    int l = 0, r = 1e9;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    printf("%d\n", l);
    
    return 0;
}

增广路径

从二分图的非匹配点开始,经过非匹配边,匹配边,非匹配边,匹配边…最后到非匹配点的路径被称为增广路径
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论
将所有匹配边删除,添加非匹配边,图中匹配的对数+1
最大匹配不存在增广路径


372. 棋盘覆盖

372. 棋盘覆盖 - AcWing题库
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

建图方式很特殊,将每个格子看成点,相邻格子之间连一条边,问题就转换成了从图中选择最多的边,使得每条边的点都不重复
这就是一个最大匹配问题
接着判断图是否是一个二分图,若不是二分图,那么不能使用匈牙利算法
n*m矩阵的奇数格和偶数格(横纵坐标之和)染上不同的颜色,相同颜色的为一组,那么整个矩阵就能被分成两个集合,由于只有相邻格子之间存在边,所以集合中的不存在边,只有集合之间存在边
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

枚举所有奇数格(或者偶数格),试着将其匹配。注意:不需要枚举坏掉的格子,匹配时也不用匹配坏掉的格子

#include <iostream>
#include <cstring>
using namespace std;

const int N = 110;
typedef pair<int, int> PII;
PII match[N][N];
bool g[N][N], st[N][N];
int dx[4] = { 0, 1, 0, -1 }, dy[4] = { 1, 0, -1, 0 };
int n, m;
    
bool find(int x, int y)
{
    for (int i = 0; i < 4; ++ i )
    {
        int nx = x + dx[i], ny = y + dy[i];
        if (!g[nx][ny] && nx >= 1 && nx <= n && ny >= 1 && ny <= n)
        {
            if (!st[nx][ny])
            {
                auto t = match[nx][ny];
                st[nx][ny] = true;
                if (t.first == 0 || find(t.first, t.second))
                {
                    match[nx][ny] = { x, y };
                    return true;
                }
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d%d", &n, &m);
    int x, y;
    while (m -- )
    {
        scanf("%d%d", &x, &y);
        g[x][y] = true;
    }
    
    
    int res = 0;
    for (int i = 1; i <= n; ++ i )
        for (int j = 1; j <= n; ++ j )
            if ((i + j) % 2 && !g[i][j])
            {
                memset(st, false, sizeof(st));
                if (find(i, j)) res ++ ;
            }
                
    printf("%d\n", res);
    return 0;
}

debug:find的判断条件if (!g[nx][ny] && nx >= 1 && nx <= n && ny >= 1 && ny <= n)!g[nx][ny]写成了!g[x][y]
每次find之前st数组没有重置


最小点覆盖

给定一个无向图,从中选出最少的点,使得每条边只有一个端点被选择
结论:最小点覆盖 = 最大匹配数


376. 机器任务

376. 机器任务 - AcWing题库
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

分析题意:有k个任务,每个任务可以在A机器或者B机器上完成,但是机器必须调整为相应的模式,任务的执行顺序任意,求任意顺序中的最少调整次数

建图:将完成每个任务需要调整的模式看成点,一个任务有两个点,在这两点之间连线。显然,得到的图是一个二分图,由于不同任务在相同机器上需要调整的模式可能相同,这些点可以看成一个点
题目要完成所有任务,即选择每条边的一个点,根据题意也就是求最小点覆盖
用匈牙利求二分图的最大匹配即可
由于每台机器的初始状态为0,所以需要调整状态为0的任务不用切换模式,直接就能完成,因此建图时不需要建立这些任务

#include <iostream>
#include <cstring>
using namespace std;

const int N = 210, M = 1010;
int h[N], e[M], ne[M], idx;
int match[N]; bool st[N];
int n1, n2, m;

void add(int x, int y)
{
    e[idx] = y, ne[idx] = h[x], h[x] = idx ++ ;
}

bool find(int x)
{
    for (int i = h[x]; i != -1; i = ne[i])
    {
        int y = e[i];
        if (!st[y])
        {
            st[y] = true;
            if (match[y] == 0 || find(match[y]))
            {
                match[y] = x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    
    while (scanf("%d", &n1), n1)
    {
        idx = 0;
        memset(h, -1, sizeof(h));
        memset(match, 0, sizeof(match));
        scanf("%d%d", &n2, &m);
        int t, x, y;
        while (m -- )
        {
            scanf("%d%d%d", &t, &x, &y);
            if (x == 0 || y == 0) continue;
            add(x, y);
        }
        
        int res = 0;
        for (int i = 1; i <= n1; ++ i)
        {
            memset(st, false, sizeof(st));
            if (find(i)) res ++ ;
        }
        printf("%d\n", res);
    }
    
    return 0;
}

最大独立集

从一个无向图中选出最多的点,使得选出的点之间都没有边
等价于去掉最少的点,将所有边破坏
等价于最小点覆盖,等价于最大匹配
假设一共n个点,最大匹配数位m,最大独立集的数量为n - m
最大团
从一个无向图中选出最多的点,使得选出的点之间都有边


378. 骑士放置

378. 骑士放置 - AcWing题库
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

建图:矩阵中,能互相攻击到的格子之间建立一条边
那么问题就转换成了求图的最大独立集,即选择的格子之间都没有边,不能相互攻击
第三章 图论 No.11二分图,匈牙利算法与点覆盖,AcWing算法提高课 课程记录,算法,图论

验证建的图是否为二分图,将奇数格和偶数格染不同的颜色,若当前坐标为 ( x , y ) (x, y) (x,y),那么该坐标之和为 x + y x + y x+y,要得到与之相连的坐标,就要将x±1,y±2,坐标之和要±一个奇数
假设坐标之和为奇数,加上奇数得到偶数,格子的颜色不同
假设坐标之和为偶数,加上奇数得到奇数,格子的颜色也不同
所以该图是一个二分图,可以使用匈牙利算法求最大匹配

#include <iostream>
#include <cstring>
using namespace std;

typedef pair<int, int> PII;
const int N = 110;
bool g[N][N], st[N][N];
PII match[N][N];
int dx[8] = { 1, 1, 2, 2, -1, -1, -2, -2 }, dy[8] = { 2, -2, 1, -1, 2, -2, 1, -1 };
int n, m, t;

bool find(int x, int y)
{
    for (int i = 0; i < 8; ++ i )
    {
        int nx = x + dx[i], ny = y + dy[i];
        if (!g[nx][ny] && nx >= 1 && nx <= n && ny >= 1 && ny <= m)
        {
            if (!st[nx][ny])
            {
                st[nx][ny] = true;
                auto t = match[nx][ny];
                if (t.first == 0 || find(t.first, t.second))
                {
                    match[nx][ny] = { x, y };
                    return true;
                }
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d%d%d", &n, &m, &t);
    int x, y;
    for (int i = 0; i < t; ++ i )
    {
        scanf("%d%d", &x, &y);
        g[x][y] = true;
    }
    int res = 0;
    for (int i = 1; i <= n; ++ i )
        for (int j = 1; j <= m; ++ j )
            if (!g[i][j] && (i + j) % 2)
            {
                memset(st, 0, sizeof(st));
                if (find(i, j)) res ++ ;
            }
            
    printf("%d\n", n * m - t- res);
    return 0;
}

debug:求最大匹配时,只需要遍历一个集合中的点,可以是奇数格也可以是偶数格,即添加条件(i + j) % 2


最小路径点覆盖

针对有向无环图,用最少的互不相交(点不重复)的路径较所有点覆盖
没听懂,先跳过文章来源地址https://www.toymoban.com/news/detail-652551.html

到了这里,关于第三章 图论 No.11二分图,匈牙利算法与点覆盖的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第三章 图论 No.1单源最短路及其综合应用

    做乘法的最短路时,若权值=0,只能用spfa来做,相等于加法中的负权边 1129. 热浪 1129. 热浪 - AcWing题库 单源最短路,稀疏图,用堆优化Dijkstra即可,就是板子套了个背景 debug:由于是无向图,边的数量要开两倍。但是 w[N] 没改,debug了很久 所以 e[M], ne[M], w[M] ,只有 h[N] ,其他

    2024年02月14日
    浏览(47)
  • 第三章 图论 No.4最小生成树的简单应用

    存在边权为负的情况下,无法求最小生成树 裸题:1140. 最短网络 1140. 最短网络 - AcWing题库 套个prim的板子即可 裸题:1141. 局域网 1141. 局域网 - AcWing题库 裸题,稀疏图,套个kruskal的板子就行 需要注意的是:题目给定的图可能存在多个连通块,若使用prim算法,需要对每个连通

    2024年02月14日
    浏览(57)
  • 第三章 图论 No.10无向图的双连通分量

    无向图有两种双连通分量 边双连通分量,e-DCC 点双连通分量,v-DCC 桥:删除这条无向边后,图变得不连通,这条边被称为桥 边双连通分量:极大的不含有桥的连通区域,说明无论删除e-DCC中的哪条边,e-DCC依旧连通 (该连通分量的任意边属于原图中的某条环)。此外,任意两

    2024年02月12日
    浏览(40)
  • 算法基础复盘笔记Day07【搜索与图论】—— Prim、Kruskal、染色体判定二分图、匈牙利算法

    ❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于 Java后端开发 ,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得 关注 、 点赞 、 收藏 、 评论 ⭐️⭐️⭐️ 📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉 1. 题目

    2024年02月02日
    浏览(50)
  • 第三章 图论 No.8最近公共祖先lca, tarjan与次小生成树

    O ( m l o g n ) O(mlogn) O ( m l o g n ) ,n为节点数量,m为询问次数,lca是一种在线处理询问的算法 自己也是自己的祖先 倍增: f a ( i , j ) fa(i, j) f a ( i , j ) 表示从i开始,向上走 2 j 2^j 2 j 步走到的点 j = 0,走到父节点 j 0,分两步走,先走到 2 j − 1 2^{j-1} 2 j − 1 步再走 2 j − 1 2^{

    2024年02月13日
    浏览(44)
  • 第三章 图论 No.6负环之01分数规划与特殊建图方式

    裸题:904. 虫洞 904. 虫洞 - AcWing题库 这个==真的服,调半天,还有,邻接表的大小又设置错了 01分数规划:361. 观光奶牛 361. 观光奶牛 - AcWing题库 在图论问题中,所有形如:某个部分之和除以某个部分之和最大的问题,被称为01分数规划,通常使用二分解决这类问题 根据题意

    2024年02月13日
    浏览(41)
  • 第三章 图论 No.9有向图的强连通与半连通分量

    连通分量是无向图的概念,yxc说错了,不要被误导 强连通分量:在一个有向图中,对于分量中的任意两点u,v,一定能从u走到v,且能从v走到u。强连通分量是一些点的集合,若加入其他点,强连通分量中的任意两点就不能互相递达 半连通分量:在一个有向图中,对于分量中

    2024年02月13日
    浏览(51)
  • 第三章 图论 No.5最小生成树之虚拟源点,完全图与次小生成树

    虚拟源点:1146. 新的开始 1146. 新的开始 - AcWing题库 与一般的最小生成树问题不同,本题需要在建立电站的电井之间建立电网,在两个电站之间建立电网需要花费金额,可以看成一条具有权值的边 但是建立电网的前提是:其中一个电井需要建立电站,建立电站也需要费用 已经

    2024年02月14日
    浏览(40)
  • 第三章 图论 No.3 flody之多源汇最短路,传递闭包,最小环与倍增

    flody的四个应用: 多源汇最短路 传递闭包 找最小环 恰好经过k条边的最短路 倍增 多源汇最短路:1125. 牛的旅行 1125. 牛的旅行 - AcWing题库 直径概念:同一连通块中,两个距离最远的点之间的距离 如何求直径?由于图中存在着两个连通块,所以直接对全图做一个flody,就能更

    2024年02月14日
    浏览(45)
  • 第三章 图论 No.2单源最短路之虚拟源点,状压最短路与最短路次短路条数

    dp是特殊的最短路,是无环图(拓扑图)上的最短路问题 1137. 选择最佳线路 1137. 选择最佳线路 - AcWing题库 对于每组测试数据,该重置的数据要重置,我没有重置idx,导致TLE 处理反向建图,还有一种扩展做法:虚拟源点 设置虚拟源点,与每个起点之间连接边权为0的边 原问题

    2024年02月14日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包