【蓝桥集训18】二分图(2 / 2)

二分图定义:将所有点分成两个集合,使得所有边只出现在集合之间,就是二分图

目录

860. 染色法判定二分图 

1、dfs

2、bfs

861. 二分图的最大匹配 - 匈牙利算法ntr算法


860. 染色法判定二分图 

活动 - AcWing

1、dfs

思路:

  • 对每一个未染色的点进行dfs,如果有一个点染色失败,说明该图不是二分图
  • 在dfs中,先对该点染色,接着遍历所有相邻节点
  • 如果相邻的点颜色和该点相同,说明该图不是二分图
  • 如果相邻点未染色,则将该点染成相反色,并递归其相邻点
  • 如果所有点均为出现染色失败的情况,则该图为二分图
import java.util.*;

class Main
{
    static int N=100010,M=N*2;
    static int[] h=new int[N],e=new int[M],ne=new int[M],color=new int[N];
    static int idx;
    
    public static void add(int a,int b)
    {
        e[idx]=b;ne[idx]=h[a];h[a]=idx++;
    }
    
    public static boolean 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]==c) return false; //如果相邻点染色与该点一样
            if(color[j]==0&&!dfs(j,3-c)) return false;  //如果未染色且染色失败
        }
        return true;
    }
    
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        
        Arrays.fill(h,-1);
        
        int n=sc.nextInt(),m=sc.nextInt();
        for(int i=0;i<m;i++)
        {
            int a=sc.nextInt(),b=sc.nextInt();
            add(a,b); add(b,a);
        }
        
        for(int i=1;i<=n;i++)
            if(color[i]==0)
                if(!dfs(i,1))
                {
                    System.out.print("No");
                    return;
                }
        System.out.print("Yes");
    }
}

2、bfs

思路:

  • 对每一个未染色的点进行bfs
  • 在bfs中,先给该点染色,将其放入队列
  • 队列循环放出与其相邻节点,如果有节点色和该点相同,则不是二分图
  • 否则将未染色的点,染与该点相反的色,存入队列中
  • 如果队空,没有出现染色失败的情况,则该图是二分图
import java.util.*;

class Main
{
    static int N=100010,M=N*2;
    static int[] h=new int[N],e=new int[M],ne=new int[M],color=new int[N];
    static int idx;
    
    public static void add(int a,int b)
    {
        e[idx]=b;ne[idx]=h[a];h[a]=idx++;
    }
    
    public static boolean bfs(int u)
    {
        color[u]=1; //先给该点染色
        Queue<PII> q=new LinkedList<>();
        q.offer(new PII(u,1));
        
        while(!q.isEmpty())
        {
            PII t=q.poll();
            int p=t.x,c=t.y;
            
            for(int i=h[p];i!=-1;i=ne[i])
            {
                int j=e[i];
                if(color[j]==c) return false;
                if(color[j]==0)
                {
                    q.offer(new PII(j,3-c));
                    color[j]=3-c;
                }
            }
        }
        return true;
        
    }
    
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        
        Arrays.fill(h,-1);
        
        int n=sc.nextInt(),m=sc.nextInt();
        for(int i=0;i<m;i++)
        {
            int a=sc.nextInt(),b=sc.nextInt();
            add(a,b); add(b,a);
        }
        
        for(int i=1;i<=n;i++)
            if(color[i]==0)
                if(!bfs(i))
                {
                    System.out.print("No");
                    return;
                }
        System.out.print("Yes");
    }
}

class PII
{
    int x,y;
    PII(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
}

861. 二分图的最大匹配 - 匈牙利算法ntr算法

活动 - AcWing

思路

匹配:在图论中,一个「匹配」是一个边的集合,其中任意两条边都没有公共顶点

最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配

 

import java.util.*;

class Main
{
    static int N=510,M=100010;
    static int[] h=new int[N],e=new int[M],ne=new int[M];
    static int[] st=new int[N]; //用于标记已经考虑过的妹子
    static int[] match=new int[N]; //用于记录当前妹子的对象
    static int idx;
    
    public static void add(int a,int b)
    {
        e[idx]=b;ne[idx]=h[a];h[a]=idx++;
    }
    
    public static boolean find(int u)
    {
        //枚举这个男生看上的所有妹子
        for(int i=h[u];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(st[j]==0) //如果这个妹子未匹配成功
            {
                st[j]=1;
                if(match[j]==0||find(match[j])) //如果这妹子没对象or妹子有对象,但她对象有备胎
                {
                    match[j]=u; //两对皆大欢喜,妹子换了新对象,前任跟备胎在一起了,两对匹配成功
                    return true;
                }
            }
        }
        return false;
    }
    
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        
        Arrays.fill(h,-1);
        
        int n1=sc.nextInt(),n2=sc.nextInt(),m=sc.nextInt();
        for(int i=0;i<m;i++)
        {
            int a=sc.nextInt(),b=sc.nextInt();
            add(a,b);  //只需要男生找女生
        }
        
        int res=0;
        for(int i=1;i<=n1;i++) //遍历每个男生
        {
            Arrays.fill(st,0);  //从头开始考虑妹子
            if(find(i)) res++;  //如果这个男生能找到妹子,则匹配数+1
        }
        System.out.print(res);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_61639349/article/details/130017201