zoukankan      html  css  js  c++  java
  • 二分图最大分配

    二分图是一个无向图,分为x,y两部分,x部中的点与y中的点往往会存在多条无向边,若x1与y2之间存在一条边,那么x1与y2可以“分配”,当然每个点部止局限于只有一条边,可以有多条,所以又有多种分配方法,为达到让这个二分图中分配数量最大,即使x1与y2可以“分配”也只是暂时的,因为要为其他点“让步”,举个例子:

    图中,点1到点2有一条边,点1到点3有一条边,点2到点4有一条边

    就“择近原则”,点1可以首先和点2“分配”,但点3发现自己只有点1可以“分配”,于是就向点1提出要求“分配”,可是点1已经被“分配过了”,于是点1就去找点2商量问它可不可以找另一个点“分配”,点2就去询问点4能否“分配”,发现点4还没有被“分配”,也就是说点2可以找另一个点分配,于是返回true,不和点1“分配”了,和点4分配,点1得到true便与点3“分配”了

    细心的人可能会发现,如果像开始那样:点1与点2分配,那么只有1个“分配组”,而经过这一系列算法(匈牙利算法)而拓展路线(增广路)便有2个“分配组”,这就称为二分图最大分配

    题目链接

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<string.h>
     4 using namespace std;
     5 int m;
     6 int n;
     7 int x,y;
     8 int ans;
     9 int match[210];                                  //记录分配目标 
    10 int put[110][3];                                 //输出 
    11 bool book[210];                                  //记录剪枝 
    12 bool way[210][210];                              //记录无向图的边 
    13 inline int read()                                //快速读入 
    14 {
    15     int sign=1,num=0;
    16     char ch=getchar();
    17     while(!isdigit(ch)){if(ch=='-')sign=-1;ch=getchar();}
    18     while(isdigit(ch)){num=num*10+(ch-'0');ch=getchar();}
    19     return sign*num;
    20 }
    21 void init()                                      //读入函数 
    22 {
    23     m=read();
    24     n=read();
    25     while(x!=-1&&y!=-1)
    26     {
    27         x=read();                                //无向边存两次 
    28         y=read();
    29         way[x][y]=true;
    30         way[y][x]=true;
    31     }
    32 }
    33 bool dfs(int x)
    34 {
    35     for(int y=m+n;y>0;--y)
    36     {
    37         if(way[x][y]&&book[y]==false)            //枚举点x的边 
    38         {
    39             book[y]=true;                        //记录点y已被查找(并非分配) 
    40             if(match[y]==0||dfs(match[y]))       //若y没有被分配或与y分配的人还有"退"的余地 
    41             {
    42                 match[x]=y;                      //储存分配目标 
    43                 match[y]=x;
    44                 return true;
    45             }
    46         }
    47     }
    48     return false;
    49 }
    50 int main()                                       //看代码建议从mian函数看起 
    51 {
    52     init();
    53     for(int i=1;i<=m+n;++i)                      //枚举点 
    54     {
    55         memset(book,false,sizeof(book));
    56         dfs(i);
    57     }
    58     for(int i=1;i<=m+n;++i)
    59         if(match[i]!=0&&match[match[i]]!=0)       //防止重复输出 
    60         {
    61             put[++ans][1]=i;
    62             put[ans][2]=match[i];
    63             match[match[i]]=0;
    64         }
    65     if(ans==0)                                   //特判 
    66     {
    67         puts("No Solution!");
    68         return 0;
    69     }
    70     printf("%d",ans); 
    71     for(int i=1;i<=ans;++i)
    72         printf("
    %d %d",put[i][1],put[i][2]);
    73 }
    View Code
  • 相关阅读:
    SQL查询语句中,any和all有什么区别?
    $(function(){...});
    在ASP.NET中TextBox和TextBoxFor的区别以及ValidationMessageFor的作用以及EditorFor等的作用和用法什么?
    Brt课程设计day3
    Brt课程设计day2
    day1
    .net 高级写法总结
    可能是目前最完整的前端框架 Vue.js 全面介绍
    redis live 如何安装
    百万级PHP网站架构工具箱
  • 原文地址:https://www.cnblogs.com/__Kgds/p/8639280.html
Copyright © 2011-2022 走看看