bzoj 2539 KM匹配

来源:互联网 发布:编程培训班 编辑:程序博客网 时间:2024/05/14 20:30

题意:2n个人,给出2n个人的坐标和姓名,然后给出一些人之间的好感,没有给出的默认好感为1。两个人之间可以匹配的条件是:两个人之间的欧几里得距离不超过给定的距离m且两人所连的线段不经过其他人。求能匹配上的人的缘分总和最大

建图慢慢建就好,然后KM匹配裸题

坑点:(1)据说坐标并没有保证是整数,

           (2)给出的两人之间的好感可能为0,所以不能匹配的人之间的边要建成负无穷

type        rec=record            xx,yy:double;            nm:string;end;var        n,m,ll,num,p1,p2:longint;        s,s1,s2         :string;        ch              :char;        i,j,k           :longint;        visx,visy       :array[0.. 35] of boolean;        link,lx,ly      :array[0..35] of longint;        w               :array[0..35,0..35] of longint;        a               :array[0..60] of rec;function min(a,b:double):double;begin   if a<b then exit(a) else exit(b);end;function max(a,b:double):double;begin   if a<b then exit(b) else exit(a);end;function find(x:longint):boolean;var        i:longint;begin   visx[x]:=true;   for i:=1 to n do     if not visy[i] and (lx[x]+ly[i]=w[x,i]) then     begin        visy[i]:=true;        if (link[i]=0) or (find(link[i])) then        begin           link[i]:=x; exit(true);        end;     end;   exit(false);end;procedure km;var        i,j,k:longint;        ans,tt:longint;begin   ans:=0;   for i:=1 to n do   begin      ly[i]:=0;      lx[i]:=-maxlongint;      for j:=1 to n do        if w[i,j]>lx[i] then lx[i]:=w[i,j];   end;   //   for i:=1 to n do   begin      while true do      begin         fillchar(visx,sizeof(visx),false);         fillchar(visy,sizeof(visy),false);         if find(i) then break;         //         tt:=maxlongint;         for j:=1 to n do          if visx[j] then            for k:=1 to n do              if (w[j,k]<>-maxlongint) then                if not visy[k] and (lx[j]+ly[k]-w[j,k]<tt) then tt:=lx[j]+ly[k]-w[j,k];         //         for j:=1 to n do         begin            if visx[j] then dec(lx[j],tt);            if visy[j] then inc(ly[j],tt);         end;      end;   end;   //   for i:=1 to n do     if link[i]>0 then inc(ans,w[link[i],i]);   writeln(ans);end;begin   readln(m);   readln(n);   for i:=1 to n*2 do   begin      read(a[i].xx,a[i].yy);      read(ch); readln(a[i].nm);      ll:=length(a[i].nm);      for j:=1 to ll do a[i].nm[j]:=upcase(a[i].nm[j]);   end;   //   for i:=1 to n do     for j:=1 to n do w[i,j]:=1;   //   readln(s);   while (s<>'End') do   begin      ll:=length(s);      for j:=1 to ll do s[j]:=upcase(s[j]);      s1:=copy(s,1,pos(' ',s)-1); delete(s,1,pos(' ',s));      s2:=copy(s,1,pos(' ',s)-1); delete(s,1,pos(' ',s));      val(s,num);      //      for j:=1 to n*2 do        if a[j].nm=s1 then break;      p1:=j;      for j:=1 to n*2 do        if a[j].nm=s2 then break;      p2:=j;      //      if p1>n then w[p2,p1-n]:=num else w[p1,p2-n]:=num;      readln(s);   end;   //   for i:=1 to n do     for j:=n+1 to 2*n do       if sqr(a[i].xx-a[j].xx)+sqr(a[i].yy-a[j].yy)>sqr(m) then w[i,j-n]:=-maxlongint else       begin          for k:=1 to 2*n do            if (k<>i) and (k<>j) then              if (a[k].yy-a[i].yy)*(a[j].xx-a[i].xx)=(a[j].yy-a[i].yy)*(a[k].xx-a[i].xx) then                if (a[k].xx<=max(a[i].xx,a[j].xx)) and (a[k].xx>=min(a[i].xx,a[j].xx)) then                  if (a[k].yy>=min(a[i].yy,a[j].yy)) and (a[k].yy<=max(a[i].yy,a[j].yy)) then                  begin                     w[i,j-n]:=-maxlongint; break;                  end;       end;   KM;end.
——by Eirlys



0 0
原创粉丝点击