首页 > 其他分享 >搜索与图论(三)-最小生成树(Prim、Kruskal)和二分图(染色法、匈牙利法)

搜索与图论(三)-最小生成树(Prim、Kruskal)和二分图(染色法、匈牙利法)

时间:2025-01-15 21:33:04浏览次数:3  
标签:二分 Prim idx int Kruskal 算法 染色法 include

目录

一、最小生成树

1.Prim算法 

2.Kruskal算法

二、二分图 

 1.判断二分图--染色体法

 2.求二分图最大匹配--匈牙利算法


一、最小生成树

1.Prim算法 

        分为朴素Prim算法和堆优化Prim算法。写法和dijikstra算法类似,堆优化过程也类似,可类比学习。首先,介绍一下朴素Prim算法。

适用于稠密图。

#include<iostream>
#include<cstring>
using namespace std;
const int N=510,INF=0x3f3f3f3f;
int g[N][N];
int dist[N];//点到集合的距离
bool st[N];//标记集合中的点
int n,m;

void prim(){
    memset(dist,0x3f,sizeof dist);
    int res=0;
    for(int i=0;i<n;i++){ //n次迭代
        int t=-1;
        for(int j=1;j<=n;j++){
            if(!st[j]&&(t==-1||dist[t]>dist[j])){
                t=j;//选择不在集合中且距离集合距离最短的点
            }
        }
        if(i&&dist[t]==INF){//不是第一次迭代且距离集合最短为INF
            puts("impossible");
            return;
        }
        if(i) res+=dist[t];//1 加入权值
        //用该点更新其他点到集合的距离
        for(int j=1;j<=n;j++) dist[j]=min(dist[j],g[t][j]);//2 注意12先后,这一步可能会因为负环改变dist[t]
        st[t]=true;
    }
    printf("%d",res);
}

int main(){
    scanf("%d%d",&n,&m);
    memset(g,0x3f,sizeof g);
    while(m--){
        int a,b,w;scanf("%d%d%d",&a,&b,&w);
        g[a][b]=g[b][a]=min(g[a][b],w);
    }
    prim();
    return 0;
}

堆优化Prim算法,适用于稀疏图。

         由于稀疏图的求解也可用Kruskal算法,且堆优化实际几乎不常用,因此根据实用主义思想,这里不具体介绍堆优化Prim算法。

2.Kruskal算法

        不需要邻接表、 邻接矩阵 来 存 图 , 用 结构体 存 边 即可。         使用到了并查集的思想。

 

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

const int N=200010;
int n,m;
int p[N];

struct Edge{
    int a,b,w;
    bool operator< (const Edge &other) const{
        return w<other.w;
    }
}edges[N];

int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        int a,b,w;scanf("%d%d%d",&a,&b,&w);
        edges[i]={a,b,w};
    }
    sort(edges,edges+m);
    for(int i=1;i<=n;i++) p[i]=i;
    int res=0,cnt=0;
    for(int i=0;i<m;i++){
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=find(a),b=find(b);
        if(a!=b){//若不连通则可加
            p[a]=b;
            res+=w;
            cnt++;
        }
    }
    if(cnt<n-1) puts("impossible");
    else printf("%d\n",res);
    return 0;
}

二、二分图 

 1.判断二分图--染色体法

        染色法的基本思想是尝试用两种颜色对图中的顶点进行染色,使得相邻顶点颜色不同。如果能够成功染色,则图是二分图;否则,图不是二分图。

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

int n,m;
const int N=100010,M=200010;
int h[N],e[M],ne[M],idx;
int color[N];

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

bool dfs(int u,int c){
    color[u]=c;
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(!color[j]){
            if(!dfs(j,3-c)) return false;
        }else if(color[j]==c) return false;//冲突
    }
    return true;
}

int main(){
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    while(m--){
        int a,b;scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    bool flag=true;
    for(int i=1;i<=n;i++){
        if(!color[i]){
            if(!dfs(i,1)){
                flag=false;
                break;
            }
        }
    }
    if(flag) puts("Yes");
    else puts("No");
    return 0;
}

 2.求二分图最大匹配--匈牙利算法

 

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

const int N=510,M=10010;

int n1,n2,m;
int h[N],e[M],ne[M],idx;
int match[N]; //存右边点匹配的左边点
bool st[N]; //每次不能重复匹配的点

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

bool find(int x){
    for(int i=h[x];i!=-1;i=ne[i]){//从它的备选中选择点进行匹配
        int j=e[i];
        if(!st[j]){ //该备选点未被匹配
            st[j]=true;//先标记为不能被匹配
            if(match[j]==0||find(match[j])){ //该点未被匹配||被匹配了但匹配它的点有其它选择
                match[j]=x;
                return true;
            }
        }
    }
    return false;
}

int main(){
    scanf("%d%d%d",&n1,&n2,&m);
    memset(h,-1,sizeof h);
    while(m--){
        int a,b;scanf("%d%d",&a,&b);
        add(a,b);//从左部分找,只需连left->right
    }
    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;
}

 

标签:二分,Prim,idx,int,Kruskal,算法,染色法,include
From: https://blog.csdn.net/a2946501058/article/details/145166859

相关文章

  • 基本类型-primitive_type
    Booleans(bool)letis_morning=true;ifis_morning{println!("Goodmorning!");}Characters(char)fnmain(){letc1='a';//字母letc2='中';//中文letc3='......
  • 漏水检测需要根据不同的情况采取不同的方法。对于一般的小范围漏水,可以先尝试目视检查
    房屋漏水问题可能出现在多个地方,包括屋顶、墙体、窗户、管道等。漏水不仅会对房屋结构和居住环境造成损害,还可能带来霉菌生长、墙面脱落等二次损害。因此,及时检测和修复漏水问题非常重要。下面是几种常见的房屋漏水检测方法:1. 目视检查法屋顶:检查屋顶瓦片是否破损、松动,或者有......
  • 什么是LPR(贷款市场报价利率,Loan Prime Rate)?它有什么用?(中英双语)
    中文版LPR是什么利率?它有什么用?LPR(贷款市场报价利率,LoanPrimeRate)是中国金融市场中一种基准贷款利率,由全国银行间同业拆借中心根据报价行的报价计算得出。LPR是银行向其最优质客户提供贷款的基础利率,同时也是其他贷款利率的定价参考基准。LPR的作用:贷款定价基准:LPR成......
  • C++Primer 变量
    欢迎阅读我的【C++Primer】专栏专栏简介:本专栏主要面向C++初学者,解释C++的一些基本概念和基础语言特性,涉及C++标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级程序设计技术。希望对读者有帮助!目录2.2变量变量......
  • Cesium-(Primitive)-(RectangleOutlineGeometry)
    RectangleOutlineGeometry以下是RectangleOutlineGeometry类的构造函数属性,以表格形式展示:属性名类型默认值描述rectangleRectangle具有北、南、东、西属性的地理矩形,单位为弧度。ellipsoidEllipsoidEllipsoid.default可选的,矩形所在的椭球体。g......
  • Cesium中级开发教程之二十八:Entity和Primitive对比
    教程示例网站:https://thomaz529.github.io 采用相同的电脑配置和谷歌浏览器,分别用Entity和Primitive绘制50400个实体,Entity的帧率是20,Primitive的帧率是59,在性能优化上,Primitive比Entity有着巨大的优势!1、EntityEntity是Cesium中用于描述具有坐标位置的实际对象的高级概念......
  • MySQL的PRIMARY KEY的DEFAULT NULL问题
    问题展示 代码一:importpymysqlif__name__=='__main__':conn=pymysql.connect(host='localhost',port=3306,user='root',passwd='123123',charset='utf8mb4',......
  • 「ARC118C」 Coprime Set
    题意给定\(n\),构造一个长度为\(n\)的数组,满足任意两个数不互质且不相同,所有数的最大公因数为\(1\),且每个数最大为\(10000\)。分析这种限制了数的大小,不限制大小和位置关系的构造题有一个套路。先找出几个最小的满足条件的数,然后找出延申的条件。对于本题,当\(n=3\)时,有......
  • 《C++Primer Plus(第6版)中文版》关键知识点笔记汇总(关键框架)
    前言《C++PrimerPluse(第6版)中文版》(后文简称CPPPP)是一部经典的C++入门书籍,作为入门书籍给我的感觉却是劝退,所以我也建议读者在读CPPPP前了解C语言或C++,他的优点也是他的缺点——讲解过细过深,有写地方深入但没有讲透彻让读者晕头转向,在加上翻译问题更是让很多人读不下去,这......
  • USACO备考冲刺必刷题 | P1218 Superprime Rib
    学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考学习过程中的题目,记录每一个瞬间。附上汇总贴:USACO备考冲刺必刷题|汇总-CSDN博客【题目描述】农民约翰的母牛总是产生最好的肋骨。你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们。农民约翰确定他卖给买方......