ssl 2601 飞行员配对方案问题

这里写图片描述
大意:最大匹配。
分析:网络流,连边,用一个原点和终点连接二分图两边。
这里写图片描述
设容量为1,求原点到终点的最大流。
(没有特殊判断的方案不管)

代码:

const
 maxn=2003;
 maxm=200003;
type
 node=record
  y,c,next,op:longint;
 end;

var
 e,n,m,s,t,ans,d,x,y,i:longint;
 ls,dis,q,cur:array [0..maxn] of longint;
 g:array [0..maxm*2] of node;
procedure add(u,v,c:longint);
begin
 inc(e);
 g[e].y:=v; g[e].c:=c; g[e].op:=e+1; g[e].next:=ls[u]; ls[u]:=e;
 inc(e);
 g[e].y:=u; g[e].c:=0; g[e].op:=e-1; g[e].next:=ls[v]; ls[v]:=e;
end;

function bfs:boolean;
 var i,head,tail,tt,u:longint;
begin
 for i:=s to t do
  dis[i]:=0;
 dis[s]:=1;
 head:=0; tail:=1;
 inc(tail);
 q[tail]:=s;
 while head<=tail do
  begin
   inc(head);
   u:=q[head];
   i:=ls[u];
   while i>0 do
    begin
     if (g[i].c<>0) and (dis[g[i].y]=0) then
      begin
       dis[g[i].y]:=dis[u]+1;
       if g[i].y=t then exit(true);
       inc(tail);
       q[tail]:=g[i].y;
      end;
     i:=g[i].next;
    end;
  end;
 exit(false);
end;

function min(x,y:longint):longint;
 begin
  if x<y then exit(x)
         else exit(y);
 end;

function dfs(x,maxf:longint):longint;
var ret,i,f:longint;
 begin
  if (x=t) or (maxf=0) then exit(maxf);
  ret:=0;
  i:=cur[x];
  while i>0 do
   begin
    if (g[i].c<>0) and (dis[g[i].y]=dis[x]+1) then
     begin
      f:=dfs(g[i].y,min(g[i].c,maxf));
      dec(g[i].c,f);
      inc(g[g[i].op].c,f);
      ret:=ret+f;
      if ret=maxf then break;
     end;
    i:=g[i].next;
   end;
  exit(ret);
 end;

procedure dinic;
 var i:longint;
begin
 while bfs do
  begin
   for i:=s to t do
    cur[i]:=ls[i];
   ans:=ans+dfs(s,maxlongint);
  end;
end;

begin
 readln(n,d);
 for i:=1 to n do
  add(0,i,1);
 for i:=n+1 to d do
  add(i,d+1,1);
 s:=0; t:=d+1;
 repeat
  readln(x,y);
  if (x=-1) and (y=-1) then break;
  add(x,y,1);
 until 1=2;
 dinic;
 if ans<>0 then writeln(ans)
           else writeln('No Solution');
end.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值