pku1815 割边
2010-05-29 14:35
120 查看
这题wa了N次,就是改某个图不改某个图的问题。。
题目大意:
一群人,1表示两个人能联系0表示两个人不能联系,一个起点s一个终点t,问最少删除多少个点能使s到t收不到信息,并且让你给出一组解,要求字典序最小。
简略题解:
显然就是最大流。
把每个点拆成两个点i,i',从i向i'连一条容量为1的边,如果i和j能联系,那么从i'向j连一条容量为无穷的边。从s向s'连一条容量为无穷的边,从t向t'连一条容量为无穷的边。那么求这个网络的最大流就是第一问。
那么如何给出一组解呢,直接dfs是不行的,因为要求字典序了。我用了一个比较shax的办法就是按字典序枚举,然后删点,看最大流是否减小,若减小了那么就记录一下并且把这个点真正删掉。。这样会很慢,然后纠结的跑了500+ms。
其实还可以用dfs会很快,就是每删掉一个点,就从t到s开始dfs一条路径,这条路径包含i’--->i,如果到了说明有解。。我是后来才搜到这种方法的,所以没改。。
附程序:
题目大意:
一群人,1表示两个人能联系0表示两个人不能联系,一个起点s一个终点t,问最少删除多少个点能使s到t收不到信息,并且让你给出一组解,要求字典序最小。
简略题解:
显然就是最大流。
把每个点拆成两个点i,i',从i向i'连一条容量为1的边,如果i和j能联系,那么从i'向j连一条容量为无穷的边。从s向s'连一条容量为无穷的边,从t向t'连一条容量为无穷的边。那么求这个网络的最大流就是第一问。
那么如何给出一组解呢,直接dfs是不行的,因为要求字典序了。我用了一个比较shax的办法就是按字典序枚举,然后删点,看最大流是否减小,若减小了那么就记录一下并且把这个点真正删掉。。这样会很慢,然后纠结的跑了500+ms。
其实还可以用dfs会很快,就是每删掉一个点,就从t到s开始dfs一条路径,这条路径包含i’--->i,如果到了说明有解。。我是后来才搜到这种方法的,所以没改。。
附程序:
program pku_1815; const inf=10000000; var a:array[0..201,0..201] of longint; c,tc,av:array[0..401,0..401] of longint; d,num:array[0..401] of longint; n,st,ed,ans,now:longint; {------------------------} procedure init; var i,j:longint; begin readln(n,st,ed); for i:=1 to n do for j:=1 to n do read(a[i,j]); if a[st,ed]=1 then begin writeln('NO ANSWER!'); halt; end; end; {------------------------} function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; {------------------------} function dfs(u,flow:longint):longint; var i,tmp:longint; begin if u=ed+n then exit(flow); dfs:=0; for i:=1 to n*2 do if (c[u,i]>0) and (d[u]=d[i]+1) then begin tmp:=dfs(i,min(flow-dfs,c[u,i])); dec(c[u,i],tmp); inc(c[i,u],tmp); inc(dfs,tmp); if dfs=flow then exit(dfs); end; if d[st]>=n*2 then exit; dec(num[d[u]]); if num[d[u]]=0 then d[st]:=n*2; inc(d[u]); inc(num[d[u]]); end; {------------------------} procedure maxflow; var flow:longint; begin ans:=0; fillchar(d,sizeof(d),0); fillchar(num,sizeof(num),0); num[0]:=n*2; while d[st]<n*2 do begin flow:=dfs(st,maxlongint); inc(ans,flow); end; end; {------------------------} function check(x:longint):boolean; begin if c[x,x+n]=1 then exit(false); if (x=st) or (x=ed) then exit(false); tc:=c; c:=av; c[x,x+n]:=0; maxflow; if now>ans then begin now:=ans; av[x,x+n]:=0; exit(true); end else begin c:=tc; exit(false); end; end; {------------------------} procedure main; var i,j:longint; begin for i:=1 to n do c[i,i+n]:=1; c[st,st+n]:=inf; c[ed,ed+n]:=inf; for i:=1 to n do for j:=1 to n do if i<>j then if a[i,j]=1 then c[i+n,j]:=inf; av:=c; tc:=c; maxflow; writeln(ans); j:=ans; now:=ans; for i:=1 to n do begin if j=0 then break; if check(i) then begin dec(j); write(i,' '); end; end; writeln; end; {------------------------} begin init; main; end.
相关文章推荐
- pku1815 最小割点集 => 拆点 + 最小割
- Toplogical sort(pku 1094 Sorting It All Out)
- pku2482 史上最浪漫的题(二叉静态检索树)
- pku 1502 MPI Maelstrom
- 离散化+树状数组pku2299
- pku 2594
- pku 2387 Til the Cows Come Home
- pku1635树的最小表示--分治递归
- PKU 3675 Telescope
- 火车进洞!!!!pku1363
- PKU 3667
- pku1083 Moving Tables
- pku 2762 Going from u to v or from v to u?
- pku 2983 差分约束系统判断
- baby_step giant_step hdu 2815 mod tree pku 3243 Clever Y
- pku 1392 Ouroboros Snake
- POJ/PKU 2513 并查集+字典树+欧拉回路
- pku 1936 LCS
- pku 1716 Integer Intervals
- pku 1275 Cashier Employment