根据题意,如果有两个点A和B,A能到达B或者B能到达A,那么两者就只能选一个。因此,首先做一遍Floyd得到任意两个点对之间能否到达,然后连边。由于最大独立子集=n-最大匹配数,所以跑一遍最大匹配就可以了。
P·S:由于bz上只有第一问的数据,所以这道题就先到此为止了。
下附AC代码:
var point,next:array[0..100000] of longint; a:array[0..200,0..200] of boolean; first,pre:array[0..10000] of longint; bo:array[0..200] of boolean; i,j,k,tot,n,m,u,v,ans:longint; procedure add(aa,bb:longint); begin tot:=tot+1; point[tot]:=bb; next[tot]:=first[aa]; first[aa]:=tot; end; function dfs(x:longint):boolean; var p,u:longint; begin p:=first[x]; while p<>0 do begin u:=point[p]; if bo[u] then begin bo[u]:=false; if (pre[u]=0) or dfs(pre[u]) then begin pre[u]:=x; exit(true); end; end; p:=next[p]; end; exit(false); end; begin readln(n,m); for i:=1 to m do begin read(u,v); a[u,v]:=true; end; for k:=1 to n do for i:=1 to n do if i<>k then for j:=1 to n do if (i<>j) and (j<>k) then a[i,j]:=a[i,j] or a[i,k] and a[k,j]; for i:=1 to n do for j:=1 to n do if (i<>j) and a[i,j] then add(i,j); ans:=n; for i:=1 to n do begin fillchar(bo,sizeof(bo),true); bo[i]:=false; if dfs(i) then ans:=ans-1; end; writeln(ans); end.
2015.2.20
by lych