忘写题解了,经典的最大密度子图
可以类似分数规划的做,二分密度,然后转化为最大权闭合子图做,判断是否大于0
注意方案的输出
const eps=1e-6;
lim=1e-12;
inf=;
type node=record
po,next:longint;
flow:double;
end; var e:array[..] of node;
numh,h,cur,pre,p,x,y:array[..] of longint;
v:array[..] of boolean;
d:array[..] of double;
len,i,n,m,t,ans:longint;
l,r,mid:double; function min(a,b:double):double;
begin
if a>b then exit(b) else exit(a);
end; procedure add(x,y:longint;f:double);
begin
inc(len);
e[len].po:=y;
e[len].flow:=f;
e[len].next:=p[x];
p[x]:=len;
end; procedure build(x,y:longint;f:double);
begin
add(x,y,f);
add(y,x,);
end; function sap:double;
var u,i,j,tmp,q:longint;
neck:double;
begin
fillchar(numh,sizeof(numh),);
fillchar(h,sizeof(h),);
numh[]:=t+;
u:=;
sap:=;
neck:=inf;
for i:= to t do
cur[i]:=p[i]; while h[]<t+ do
begin
d[u]:=neck;
i:=cur[u];
while i<>- do
begin
j:=e[i].po;
if (e[i].flow>lim) and (h[u]=h[j]+) then
begin
neck:=min(neck,e[i].flow);
pre[j]:=u;
cur[u]:=i;
u:=j;
if u=t then
begin
sap:=sap+neck;
while u<> do
begin
u:=pre[u];
j:=cur[u];
e[j].flow:=e[j].flow-neck;
e[j xor ].flow:=e[j xor ].flow+neck;
end;
neck:=inf;
end;
break;
end;
i:=e[i].next;
end;
if i=- then
begin
dec(numh[h[u]]);
if numh[h[u]]= then break;
q:=-;
tmp:=t;
i:=p[u];
while i<>- do
begin
j:=e[i].po;
if e[i].flow>lim then
if h[j]<tmp then
begin
q:=i;
tmp:=h[j];
end;
i:=e[i].next;
end;
h[u]:=tmp+;
inc(numh[h[u]]);
cur[u]:=q;
if u<> then
begin
u:=pre[u];
neck:=d[u];
end;
end;
end;
end; function dfs(x:longint):boolean;
var i,y:longint;
begin
if x=t then exit(true);
i:=p[x];
v[x]:=true;
while i<>- do
begin
y:=e[i].po;
if (e[i].flow>lim) and not v[y] then
if dfs(y) then exit(true);
i:=e[i].next;
end;
exit(false);
end; function check(w:double):boolean;
var i:longint;
f:double;
begin
len:=-;
fillchar(p,sizeof(p),);
for i:= to m do
begin
build(x[i]+m,i,inf);
build(y[i]+m,i,inf);
build(i,t,);
end;
for i:= to n do
build(,i+m,w);
f:=sap;
if m-f> then
begin
ans:=;
for i:= to n do
begin
fillchar(v,sizeof(v),false);
if dfs(i+m) then inc(ans);
end;
exit(true);
end;
exit(false);
end; begin
readln(n,m);
for i:= to m do
readln(x[i],y[i]);
t:=n+m+;
l:=;
r:=m;
while l+eps<r do
begin
mid:=(l+r)/;
if check(mid) then l:=mid
else r:=mid;
end;
if m= then ans:=; //必须要选
writeln(ans);
end.