[PKU 3715]Blue and Red(最小点覆盖集)
2010-05-01 21:14
417 查看
【题目大意】:
军事演习 分为红蓝方
但是有的兵是好友 不能被分在不同方
问最少删掉多少人 满足条件
输出 删掉人的序号(字典序最小)
【题目分析】:
一个天津的童鞋问我的~看了看……最开始悲剧了一下~
写写发现还可以,1A之~
比较裸的一个最小点覆盖集,konig定理证明就自己翻书吧~M67那里也有……
现在比较集中的问题在于字典序的问题。经典的方法就是试删。
因为原来就是一个二分图,所以我们就不该变原来的结构,0集合的都在左边,1集合的都在右边~
这样我们得到一个初始匹配,枚举点,删点,对于在X部的点,找匹配的Y点,然后沿着反向边找增广路,如果找不到,那么就这个点就删掉,否则不删~(P.s.找到增广路相当于找到了删除点的替代品~)
对于Y部的点,沿着正向边找增广路~然后情况同上。所以要写两个find函数~
【代码(为了省工写的是邻接矩阵~)】:
军事演习 分为红蓝方
但是有的兵是好友 不能被分在不同方
问最少删掉多少人 满足条件
输出 删掉人的序号(字典序最小)
【题目分析】:
一个天津的童鞋问我的~看了看……最开始悲剧了一下~
写写发现还可以,1A之~
比较裸的一个最小点覆盖集,konig定理证明就自己翻书吧~M67那里也有……
现在比较集中的问题在于字典序的问题。经典的方法就是试删。
因为原来就是一个二分图,所以我们就不该变原来的结构,0集合的都在左边,1集合的都在右边~
这样我们得到一个初始匹配,枚举点,删点,对于在X部的点,找匹配的Y点,然后沿着反向边找增广路,如果找不到,那么就这个点就删掉,否则不删~(P.s.找到增广路相当于找到了删除点的替代品~)
对于Y部的点,沿着正向边找增广路~然后情况同上。所以要写两个find函数~
【代码(为了省工写的是邻接矩阵~)】:
program PKU_3715; var g:array[0..300,0..300] of boolean; belongs,linkx,linky:array[0..300] of longint; v,del:array[0..300] of boolean; n,m,i,x,ans,tt,ttt,y:longint; function find1(x:longint):boolean; var i:longint; begin if del[x] then exit(false); for i:=1 to n do if g[x,i] and not v[i] and not del[i] then begin v[i]:=true; if (linky[i]=0) or find1(linky[i]) then begin linky[i]:=x; linkx[x]:=i; exit(true); end; end; exit(false); end; function find2(x:longint):boolean; var i:longint; begin if del[x] then exit(false); for i:=1 to n do if g[i,x] and not v[i] and not del[i] then begin v[i]:=true; if (linkx[i]=0) or find2(linkx[i]) then begin linky[x]:=i; linkx[i]:=x; exit(true); end; end; exit(false); end; begin assign(input,'a.in'); assign(output,'a.out'); reset(input); rewrite(output); readln(tt); for ttt:=1 to tt do begin readln(n,m); for i:=1 to n do read(belongs[i]); fillchar(g,sizeof(g),0); for i:=1 to m do begin readln(x,y); inc(x); inc(y); if (belongs[x]=0) and (belongs[y]=1) then g[x,y]:=true; if (belongs[x]=1) and (belongs[y]=0) then g[y,x]:=true; end; fillchar(linkx,sizeof(linkx),0); fillchar(linky,sizeof(linky),0); fillchar(del,sizeof(del),0); ans:=0; for i:=1 to n do begin fillchar(v,sizeof(v),0); if find1(i) then inc(ans); end; write(ans); for i:=1 to n do if belongs[i]=0 then begin x:=linkx[i]; if x=0 then continue; linky[x]:=0; linkx[i]:=0; del[i]:=true; fillchar(v,sizeof(v),0); if not find2(x) then write(' ',i-1) else del[i]:=false; end else begin x:=linky[i]; if x=0 then continue; linkx[x]:=0; linky[i]:=0; del[i]:=true; fillchar(v,sizeof(v),0); if not find1(x) then write(' ',i-1) else del[i]:=false; end; writeln; end; close(input); close(output); end.
相关文章推荐
- poj3715——Blue and Red//最小顶点覆盖
- poj 3715 Blue and Red(二分图最大匹配匈牙利算法)
- POJ 3715 Blue and Red 二分图
- poj 3715 Blue and Red(二分图最大匹配+字典序输出)
- Red/Blue Spanning Tree----HDU_4263----并查集and生成树
- cf B Red and Blue Balls
- PKU 1979 Red and Black
- pku3715 Blue and Red
- Codeforces Round #233 (Div. 2) B. Red and Blue Balls
- pku 1979 Red and Black---dfs
- [agc14e]Blue and Red Tree
- 【AGC014】E - Blue and Red Tree
- poj 3715 最小覆盖集,并且输出字典序最小解
- [PKU 2125]Destroying the Graph(二分图最小权覆盖集)
- codeforces#233_div2_B Red and Blue Balls
- AC日记——Red and Blue Balls codeforces 399b
- codeforces#233_div2_B Red and Blue Balls
- HDU4263 Red Blue Spanning Tree 最小生成树活用
- HDU 4263 Red/Blue Spanning Tree(最小生成树)
- HDU 4263 Red/Blue Spanning Tree【最小生成树原理】