二分图最大分配

二分图是一个无向图,分为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
原文地址:https://www.cnblogs.com/__Kgds/p/8639280.html