二分图的概念

[复制链接]
发表于 2023-12-30 10:01:24 | 显示全部楼层 |阅读模式
二分图的概念
设G=(V,E)是一个无向图,如果顶点V可分割两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。如下图是一个二分图
         


上图可以存储为邻接矩阵: (0 0 0 1 1 10            也可以存储为(1 1 1 0
                       0 0 0 0 1 01                        0 1 0 1
                       0 0 0 1 0 10                        1 0 1 0)
                       1 0 1 0 0 0 0
                       1 1 0 0 0 0 0
                       1 0 1 0 0 0 0
                       0 1 0 0 0 0 0 )
5. 2 最大匹配
1.最大匹配的概念
设G=(V,E)是一个图,如果M是边E的子集,且M中的任意两条边都不与同一个顶点相关联,则称M是G的一个匹配。G的边数最多的匹配称为G的最大匹配。
2最大匹配算法
最大流方法
1) 将图变成单向有向图A-->B
2) 添加源点s和汇点t将图变为 s-->A-->B-->t,  如上图一可变为

                   图2
3)设每条有向边的容量c为1
4)源点到汇点的最大流即为最大匹配
  例一:混双配对问题:
乒乓球队中有N名男运动员和M名女运动员。由于某种原因,在混双比赛中,某些男运动员和某些女运动员不能配对比赛,这使得教练很苦恼,他希望你能帮他找出一种最优得配对方案,组成今尽可能最多得混双配对。
输入文件:第一行两个正整数N,M(N+M<=100),表示男、女运动的个数。以下是一个N×M的矩阵。若Aij=1表示第i名男运动员可与第j名女运动员配对;若Aij=0则表示不能配对。
输出文件:只有一个整数,为最多的混双配对。
程序如下:
program tpp1;
const inf='input.txt';
      maxn=100;
type
arc=record
  c, f:integer;
end;
node=record
  last:integer;
  checked:boolean;
end;
var
map:array[1..maxn+2,1..maxn+2] of arc;
imp:array[1..maxn+2] of node;
n,m,s,t:integer;
fp:text;
procedure init;
var i,j:integer;
begin
assign(fp,inf);
reset(fp);
readln(fp,n,m);
fillchar(map,sizeof(map),0);
for i:=1 to n do
  for j:=1 to m do
   read(fp,map[i,n+j].c);
s:=n+m+1;
t:=n+m+2;
for i:=1 to n do map[s,i].c:=1;
for i:=1 to m do map[i+n,t].c:=1;
close(fp);
end;
procedure main;
var flow,i:integer;
function find:boolean;
  var i,j:integer;
  begin
   find:=false;
   fillchar(imp,sizeof(imp),0);
   imp.last:=s;
   repeat
    i:=1;
    while (i<=n+m+2) and ((imp.last=0) or imp.checked)do inc(i);
    if i>n+m+2 then exit;
    for j:=1 to n+m+2 do
      if imp[j].last=0 then begin
       if map[i,j].f<map[i,j].c thenimp[j].last:=i else
        if map[j,i].f>0 thenimp[j].last:=-i; end;
    imp.checked:=true;
   until imp[t].last<>0;
   find:=true;
  end;
procedure updata;
var i,j:integer;
begin
  i:=t;j:=abs(imp.last);
  repeat
   if imp.last>0 then inc(map[j,i].f) else dec(map[i,j].f);
   i:=j;j:=abs(imp.last);
  until i=s;
end;
begin
  while find do updata;
  flow:=0;
  for i:=1 to n do inc(flow,map[s,i].f);
  writeln('maxpp=',flow);
end;
begin
init;
main;
end.

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表