登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

z55250825

一只蒟蒻

 
 
 

日志

 
 

【网络流24题】【二分图多重匹配】【试题库问题】  

2014-01-25 17:11:15|  分类: AC题目 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
    这道题目我们归一下类,就是有N个点,每一个点都指向若干个点,然后从N个点中选择若干个点,每一个点仅连一个后继结点,使后继结点的入度满足要求入度数,能做到即输出方案,否则NO SOLUTION。
    然后还是构图....首先一道试题只能应用于一条边,我们把试题看做点,要求的种类看做点,连一条容量为1的边即可。然后为了保证每一个试题只能用一次,所以建一个源点,给源点和试题连一条容量为1的边,然后又必须保证每一个种类有对应数目的题目,所以就再建汇点,给种类和汇点连一条容量为其要求数的边,跑最大流,如果最大流等于汇点处的容量之和,则有解,否则无解。
    这里的每一个种类可以和多个试题匹配,所以是二分图多重匹配问题
====================================================

program paper;
const maxn=2000;
var n,m:longint;
    g:array[0..maxn,0..maxn]of longint;
    que,d:array[0..maxn]of longint;
    v:array[0..maxn]of boolean;

function min(a,b:longint):longint;
begin
  if a<b then exit(a) else exit(b);
end;

function bfs(s,t:longint):boolean;
var i,l,r,u:longint;
begin
  fillchar(que,sizeof(que),0);
  fillchar(d,sizeof(d),0);
  fillchar(v,sizeof(v),false);
  l:=0;r:=1;que[l]:=s;v[s]:=true;
  while l<r do
   begin
     u:=que[l];
     for i:=0 to n+m+1 do
      if (g[u][i]>0)and(not v[i]) then
       begin
         que[r]:=i;
         inc(r);
         d[i]:=d[u]+1;
         v[i]:=true;
       end;
     inc(l);
   end;
  exit(v[t]);
end;

function dfs(p,a,t:longint):longint;
var flow,f,i:longint;
begin
  if (p=t)or(a=0) then exit(a);
  flow:=0;
  for i:=0 to n+m+1 do
   if (g[p][i]>0)and(d[i]=d[p]+1)then
    begin
      f:=dfs(i,min(g[p][i],a),t);
      inc(flow,f);
      inc(g[i][p],f);
      dec(g[p][i],f);
      dec(a,f);
      if a=0 then break;
    end;
  exit(flow);
end;

function dinic(s,t:longint):longint;
var ans:longint;
begin
  ans:=0;
  while bfs(s,t) do
    ans:=ans+dfs(s,maxlongint,t);
  exit(ans);
end;

procedure init;
var tot,i,j,k,p,ans:longint;
begin
  fillchar(g,sizeof(g),255);
  read(m,n);
  tot:=0;
  for i:=1 to m do
    begin
      read(j);
      g[i+n][n+m+1]:=j;
      g[n+m+1][i+n]:=0;
      inc(tot,j);
    end;
  for i:=1 to n do
   begin
     g[0][i]:=1;
     g[i][0]:=0;
     read(k);
     for j:=1 to k do
      begin
        read(p);
        g[i][p+n]:=1;
        g[p+n][i]:=0;
      end;
   end;
  ans:=dinic(0,n+m+1);
  if ans<>tot then begin write('No Solution!');exit;end;
  for i:=1+n to m+n do
  begin
   write(i-n,':');
   for j:=1 to n do
     if g[j][i]=0 then write(j,' ');
   writeln;
  end;
end;

begin
  assign(input,'f.in');reset(input);
  init;
  close(input);
end.



  评论这张
 
阅读(62)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018