您的位置:首页 > Web前端

[PKU 3155]Hard Life(最大密度子图)

2010-04-30 13:17 274 查看
【题目描述】:

求一个无边权点权的无向图的最大密度子图~

【题目分析】:

这题Amber论文上有一个很另类的构图……我基本明白,但是也还是有点蒙,所以这里就不写了,有兴趣的可以自己看看。

我的方法很常规,首先必须要二分密度,然后重新构图。我们发现这个0/1规划的分子分母有依赖关系,所以变得比较悲剧。但是先看看发现取每个边的条件就是必须取到两个端点,结果这个悲剧的东西就变成了和最大获利一样的模型了。构图也很简单,把边也看成点,然后代表边的点到t连容量为1的边,s到点连容量为x(二分的答案)的边。

这题要注意精度(我就是借鉴了下先人,所以还是比较顺利),还有就是那个输出(现在我也不明白为什么我开始会presentation error~)

【代码】:

program PKU_3155;
const
inf=1e8;
type
ntype=record
data,op,next:longint;
c:double;
end;
etype=record
x,y,w:longint;
end;
var
dis,vh,g:array[0..2002] of longint;
edges:array[1..5000] of etype;
v:array[0..2002] of boolean;
node:array[0..200000] of ntype;
ou:array[0..1001] of longint;
tot,n,m,s,t,nn,i,all:longint;
le,ri,mid,ans,best:double;
function min2(x,y:double):double;
begin
if x<y then exit(x)
else exit(y);
end;
procedure link(x,y:longint;w:double);
begin
inc(tot); node[tot].data:=y; node[tot].c:=w;
node[tot].op:=tot+1; node[tot].next:=g[x]; g[x]:=tot;
inc(tot); node[tot].data:=x; node[tot].c:=0;
node[tot].op:=tot-1; node[tot].next:=g[y]; g[y]:=tot;
end;
function aug(x:longint;flow:double):double;
var
bak,tmp:double; min,p:longint;
begin
if x=t then exit(flow);
min:=nn-1; bak:=flow;
p:=g[x];
while p<>0 do
begin
if node[p].c>0 then
begin
if dis[node[p].data]+1=dis[x] then
begin
tmp:=aug(node[p].data,min2(bak,node[p].c));
node[p].c:=node[p].c-tmp;
node[node[p].op].c:=node[node[p].op].c+tmp;
bak:=bak-tmp;
if dis[s]>=nn then exit(flow-bak);
if bak=0 then break;
end;
if dis[node[p].data]<min then min:=dis[node[p].data];
end;
p:=node[p].next;
end;
if bak-flow=0 then
begin
dec(vh[dis[x]]);
if vh[dis[x]]=0 then dis[s]:=nn;
dis[x]:=min+1;
inc(vh[dis[x]]);
end;
exit(flow-bak);
end;
procedure init(x:double);
var
i:longint;
begin
tot:=0;
fillchar(node,sizeof(node),0);
fillchar(g,sizeof(g),0);
for i:=1 to n do
link(s,i,x);
for i:=1 to m do
begin
link(n+i,t,1);
link(edges[i].x,n+i,inf); link(edges[i].y,n+i,inf);
end;
end;
procedure dfs(x:longint);
var
p:longint;
begin
v[x]:=true;
p:=g[x];
while p<>0 do
begin
if not v[node[p].data] and (abs(node[p].c)>1e-6) then
dfs(node[p].data);
p:=node[p].next;
end;
end;
begin
assign(input,'a.in');
assign(output,'a.out');
reset(input); rewrite(output);
readln(n,m);
s:=0; t:=n+m+1; nn:=n+m+2;
for i:=1 to m do
readln(edges[i].x,edges[i].y);
if m=0 then
begin
all:=1;
ou[1]:=1;
end
else
begin
le:=0; ri:=m;
while ri-le>1e-6 do
begin
mid:=(le+ri)/2;
init(mid);
fillchar(dis,sizeof(dis),0);
fillchar(vh,sizeof(vh),0); vh[0]:=nn; ans:=m;
while dis[s]<nn do ans:=ans-aug(s,inf);
if ans<=1e-4 then ri:=mid
else begin best:=mid; le:=mid; end;
end;
init(best);
fillchar(dis,sizeof(dis),0);
fillchar(vh,sizeof(vh),0); vh[0]:=nn; ans:=m;
while dis[s]<nn do ans:=ans-aug(s,inf);
dfs(s); all:=0;
for i:=1 to n do
if not v[i] then
begin
inc(all);
ou[all]:=i;
end;
end;
writeln(all);
for i:=1 to all do
writeln(ou[i]);
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: