NOI2006最大获利
终于搞明白了……
x到y有边意味着选x必须选y,所以才会有闭合子图中一个点的后继一定也在这个闭合子图中。
接下来按照s连正权,负权连t就ok了
1 type node=record 2 go,next,c:longint; 3 end; 4 var i,n,m,s,t,max,tmp,ans,tot,x,y,z:longint; 5 h,first,q,cur:array[0..100000] of longint; 6 e:array[0..500000] of node; 7 function min(x,y:longint):longint; 8 begin 9 if x<y then exit(x) else exit(y); 10 end; 11 procedure insert(x,y,z:longint); 12 begin 13 inc(tot); 14 e[tot].go:=y; 15 e[tot].c:=z; 16 e[tot].next:=first[x]; 17 first[x]:=tot; 18 inc(tot); 19 e[tot].go:=x; 20 e[tot].c:=0; 21 e[tot].next:=first[y]; 22 first[y]:=tot; 23 end; 24 procedure init; 25 begin 26 readln(n,m); 27 s:=0;t:=m+n+1;tot:=1; 28 for i:=1 to n do 29 begin 30 read(x); 31 insert(s,i,x); 32 end; 33 max:=0; 34 for i:=1 to m do 35 begin 36 readln(x,y,z);inc(max,z); 37 insert(n+i,t,z); 38 insert(x,n+i,maxlongint>>2); 39 insert(y,n+i,maxlongint>>2); 40 end; 41 end; 42 function bfs:boolean; 43 var i,x,y,head,tail:longint; 44 begin 45 fillchar(h,sizeof(h),0); 46 head:=0;tail:=1;q[1]:=s;h[s]:=1; 47 while head<tail do 48 begin 49 inc(head); 50 x:=q[head]; 51 i:=first[x]; 52 while i<>0 do 53 begin 54 y:=e[i].go; 55 if (h[y]=0) and (e[i].c<>0) then 56 begin 57 h[y]:=h[x]+1; 58 inc(tail); 59 q[tail]:=y; 60 end; 61 i:=e[i].next; 62 end; 63 end; 64 exit(h[t]<>0); 65 end; 66 function dfs(x,f:longint):longint; 67 var i,tmp,used:longint; 68 begin 69 if (x=t) or (f=0) then exit(f); 70 tmp:=0;used:=0; 71 i:=cur[x]; 72 while i<>0 do 73 begin 74 y:=e[i].go; 75 if (e[i].c<>0) and (h[y]=h[x]+1) then 76 begin 77 tmp:=dfs(y,min(e[i].c,f-used)); 78 dec(e[i].c,tmp); 79 inc(e[i xor 1].c,tmp); 80 if e[i].c<>0 then cur[x]:=i; 81 inc(used,tmp); 82 if used=f then exit(f); 83 end; 84 i:=e[i].next; 85 end; 86 if used=0 then h[x]:=-1; 87 exit(used); 88 end; 89 procedure dinic; 90 begin 91 ans:=0; 92 while bfs do 93 begin 94 for i:=0 to t do cur[i]:=first[i]; 95 inc(ans,dfs(0,maxlongint>>2)); 96 end; 97 end; 98 procedure main; 99 begin 100 dinic; 101 writeln(max-ans); 102 end; 103 begin 104 init; 105 main; 106 end.