最大密度子图
BZOJ1312
转换为最大权闭合子图
#include <cstdio> #include <cstring> #define LDB long double using namespace std; const LDB eps=1e-6; int cnt,nd[4001],dep[4001],sor,dl[4001],sta[1000001],tar,cur[4001],n,m,x[4001],y[4001],b[4001],ans; struct edge{ int next,des,fr; LDB cap; }sid[1000001]; void addedge(int u,int v,LDB cap){ sid[cnt].next=nd[u];sid[cnt].des=v;sid[cnt].cap=cap;nd[u]=cnt;sid[cnt].fr=u;cnt++; sid[cnt].next=nd[v];sid[cnt].des=u;sid[cnt].cap=0;nd[v]=cnt;sid[cnt].fr=v;cnt++; } int bfs(){ memset(dep,-1,sizeof(dep)); int head=1,tail=1; dep[sor]=0;dl[head]=sor; while (head<=tail){ for (int p=nd[dl[head]];p!=-1;p=sid[p].next) if ((dep[sid[p].des]==-1)&&(sid[p].cap>eps)) dep[sid[p].des]=dep[dl[head]]+1,dl[++tail]=sid[p].des; head++; } if (dep[tar]==-1) return(0);else return(1); } LDB dinic(){ LDB maxflow=0; while (bfs()){ for (int i=0;i<=tar;i++) cur[i]=nd[i]; int u=sor,top=0; while(1){ if (u==tar){ LDB mi=1e9;int last; for (int i=1;i<=top;i++) if (sid[sta[i]].cap<mi) {mi=sid[sta[i]].cap;last=i;} for (int i=1;i<=top;i++) sid[sta[i]].cap-=mi,sid[sta[i]^1].cap+=mi; u=sid[sta[last]].fr;cur[u]=sid[cur[u]].next;top=last-1; maxflow+=mi; continue; } while((cur[u]!=-1)&&((sid[cur[u]].cap<eps)||(dep[sid[cur[u]].des]!=dep[u]+1))) cur[u]=sid[cur[u]].next; if (cur[u]!=-1){sta[++top]=cur[u];u=sid[cur[u]].des;continue;} else{ if (u==sor) break; dep[u]=-1; u=sid[sta[top--]].fr; continue; } } } return(maxflow); } void build(LDB mid){ sor=0,tar=n+m+1; for (int i=sor;i<=tar;i++) nd[i]=-1; for (int i=1;i<=m;i++) addedge(0,i,1),addedge(i,m+x[i],1e9),addedge(i,m+y[i],1e9); for (int i=1;i<=n;i++) addedge(m+i,tar,mid); } void dfs(int po){ b[po]=1; if (po>m&&po<n+m+1) ans++; for (int p=nd[po];p!=-1;p=sid[p].next) if (!b[sid[p].des]&&sid[p].cap>eps) dfs(sid[p].des); } int main(){ scanf("%d%d",&n,&m); if (m==0){ printf("1\n");return(0); } for (int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]); LDB l=0,r=m; while (r-l>1.0/n/n){ LDB mid=(l+r)/2; build(mid); LDB ans=m-dinic(); if (ans<eps) r=mid;else l=mid; } build(l); dinic(); dfs(0); printf("%d\n",ans); }