题意: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