bzoj2539

这道题真的不难,但是细节挺多(具体见程序)
题目本身而言,显然是个费用流模型(或者写KM)

  1 type node=record
  2        point,next,flow,cost:longint;
  3      end;
  4 
  5 var p,x,y,pre,cur,d:array[0..80] of longint;
  6     v:array[0..80] of boolean;
  7     q:array[0..500010] of longint;
  8     edge:array[0..200010] of node;
  9     a:array[0..80,0..80] of longint;
 10     na:array[0..80] of string[21];
 11     t,n,i,len,j,k:longint;
 12     ef:boolean;
 13     s:string;
 14     ch:char;
 15 
 16 function find(x:string):longint;
 17   var i:longint;
 18   begin
 19     for i:=1 to 2*n do
 20       if na[i]=x then exit(i);
 21   end;
 22 
 23 function check(l,r:longint):boolean;
 24   var i:longint;
 25   begin
 26     for i:=1 to 2*n do
 27       if (i<>l) and (i<>r) then
 28         if ((x[i]<=x[l]) and (x[i]>=x[r])) or ((x[i]>=x[l]) and (x[i]<=x[r])) then
 29           if ((y[i]<=y[l]) and (y[i]>=y[r])) or ((y[i]>=y[l]) and (y[i]<=y[r])) then
 30             if (x[i]-x[l])*(y[i]-y[r])=(x[i]-x[r])*(y[i]-y[l]) then
 31             begin  //注意是线段上的点
 32               exit(false);
 33             end;
 34     exit(true);
 35   end;
 36 
 37 procedure add(x,y,f,w:longint);
 38   begin
 39     inc(len);
 40     edge[len].point:=y;
 41     edge[len].flow:=f;
 42     edge[len].cost:=w;
 43     edge[len].next:=p[x];
 44     p[x]:=len;
 45   end;
 46 
 47 function spfa:boolean;
 48   var i,j,f,r,x,y:longint;
 49   begin
 50     for i:=1 to t do
 51       d[i]:=-100000007;
 52     d[0]:=0;
 53     f:=1;
 54     r:=1;
 55     fillchar(v,sizeof(v),false);
 56     q[1]:=0;
 57     v[0]:=true;
 58     while f<=r do
 59     begin
 60       x:=q[f];
 61       v[x]:=false;
 62       i:=p[x];
 63       while i<>-1 do
 64       begin
 65         y:=edge[i].point;
 66         if edge[i].flow>0 then
 67           if d[x]+edge[i].cost>d[y] then
 68           begin
 69             pre[y]:=x;
 70             cur[y]:=i;
 71             d[y]:=d[x]+edge[i].cost;
 72             if not v[y] then
 73             begin
 74               inc(r);
 75               q[r]:=y;
 76               v[y]:=true;
 77             end;
 78           end;
 79         i:=edge[i].next;
 80       end;
 81       inc(f);
 82     end;
 83     if d[t]=-100000007 then exit(false) else exit(true);
 84   end;
 85 
 86 function maxcost:longint;
 87   var i,j:longint;
 88   begin
 89     maxcost:=0;
 90     while spfa do
 91     begin
 92       maxcost:=maxcost+d[t];
 93       i:=t;
 94       while i<>0 do
 95       begin
 96         j:=cur[i];
 97         dec(edge[j].flow);
 98         inc(edge[j xor 1].flow);
 99         i:=pre[i];
100       end;
101     end;
102   end;
103 
104 begin
105   len:=-1;
106   fillchar(p,sizeof(p),255);
107   readln(k);
108   readln(n);
109   for i:=1 to 2*n do
110   begin
111     readln(x[i],y[i],ch,na[i]);
112     for j:=1 to length(na[i]) do
113       na[i][j]:=upcase(na[i][j]);  //注意不区分大小写
114   end;
115   t:=2*n+1;
116   for i:=1 to n do
117   begin
118     add(0,i,1,0);
119     add(i,0,0,0);
120     add(i+n,t,1,0);
121     add(t,i+n,0,0);
122   end;
123 
124   for i:=1 to n do
125     for j:=n+1 to 2*n do
126       a[i,j]:=1;   //注意
127   ef:=true;
128   while ef do
129   begin
130     s:='';
131     read(ch);
132     while ch<>' ' do
133     begin
134       s:=s+upcase(ch);
135       if s='END' then ef:=false;  //大坑,有的人名字里会带end
136       read(ch);
137       if not ef and (ord(ch)>=65)  then
138         ef:=true
139       else if not ef then break;
140     end;
141     if not ef then break;
142     i:=find(s);
143     s:='';
144     read(ch);
145     while ch<>' ' do
146     begin
147       s:=s+upcase(ch);
148       read(ch);
149     end;
150     j:=find(s);
151     readln(a[i,j]);
152     a[j,i]:=a[i,j];
153   end;
154   for i:=1 to n do
155     for j:=n+1 to 2*n do
156       if (sqr(x[i]-x[j])+sqr(y[i]-y[j])<=sqr(k)) and check(i,j) then
157       begin
158         add(i,j,1,a[i,j]);
159         add(j,i,0,-a[i,j]);
160       end;
161   writeln(maxcost);
162 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473103.html