题意:最大密度子图
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=1105,M=4005,INF=1e9; const double eps=1e-6; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,m,u[N],v[N],s,t; struct edge{ int v,ne; double c,f; }e[M<<1]; int cnt,h[N]; inline void ins(int u,int v,double c){ cnt++; e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt; } int cur[N],d[N],vis[N]; int q[N],head,tail; bool bfs(){ head=tail=1; memset(vis,0,sizeof(vis)); d[s]=1;vis[s]=1;q[tail++]=s; while(head!=tail){ int u=q[head++]; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(!vis[v]&&e[i].c>e[i].f){ vis[v]=1;d[v]=d[u]+1; q[tail++]=v; if(v==t) return true; } } } return false; } double dfs(int u,double a){ if(u==t||a==0) return a; double flow=0,f; for(int &i=cur[u];i;i=e[i].ne){ int v=e[i].v; if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].c-e[i].f,a)))>0){ flow+=f; e[i].f+=f; e[((i-1)^1)+1].f-=f; a-=f; if(a==0) break; } } if(a) d[u]=-1; return flow; } double dinic(){ double flow=0; while(bfs()){ for(int i=s;i<=t;i++) cur[i]=h[i]; flow+=dfs(s,INF); } //printf("dinic %lf ",flow); return flow; } void bfsSol(){ head=tail=1; memset(vis,0,sizeof(vis)); q[tail++]=s;vis[s]=1; while(head!=tail){ int u=q[head++]; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(!vis[v]&&e[i].c>e[i].f){ vis[v]=1; q[tail++]=v; } } } } bool check(double x){ cnt=0; memset(h,0,sizeof(h)); for(int i=1;i<=n;i++) ins(i,t,x); for(int i=1;i<=m;i++){ ins(s,n+i,1); ins(n+i,u[i],INF); ins(n+i,v[i],INF); } return m-dinic()>eps;//eps } void solve(){ double l=1.0/n,r=m,eps=1.0/(n*n),ans=0; while(r-l>eps){ double mid=(l+r)/2;//printf("erfen %lf %lf %lf ",l,r,mid); if(check(mid)) ans=max(ans,mid),l=mid+eps; else r=mid-eps; } //printf("hi %lf ",l); check(ans); bfsSol(); int num=0; for(int i=1;i<=n;i++) if(vis[i]) num++; printf("%d ",num); for(int i=1;i<=n;i++) if(vis[i]) printf("%d ",i); } int main(){ //freopen("in.txt","r",stdin); n=read();m=read();s=0;t=n+m+1; if(!m){printf("1 1");return 0;} for(int i=1;i<=m;i++) u[i]=read(),v[i]=read(); solve(); }
今天又写了一次,只要$dinic$中判断$a==0$加一个精度就可以过了...
另一种做法不学了...
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=1105,M=4005,INF=1e9; const double eps=1e-6; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,m,u[N],v[N],s,t; struct edge{ int v,ne; double c,f; }e[M<<1]; int cnt,h[N]; inline void ins(int u,int v,double c){ cnt++; e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt; } bool vis[N]; int d[N],q[N],head,tail; int cur[N]; bool bfs(){ memset(vis,0,sizeof(vis)); head=tail=1; d[s]=0;vis[s]=1;q[tail++]=s; while(head!=tail){ int u=q[head++]; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(!vis[v]&&e[i].c>e[i].f){ vis[v]=1; q[tail++]=v; d[v]=d[u]+1; if(v==t) return true; } } } return false; } double dfs(int u,double a){ if(u==t||abs(a)<eps) return a; double flow=0,f; for(int &i=cur[u];i;i=e[i].ne){ int v=e[i].v; if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].c-e[i].f,a)))>0){ flow+=f; e[i].f+=f; e[((i-1)^1)+1].f-=f; a-=f; if(a==0) break; } } if(a) d[u]=-1; return flow; } double dinic(){ double flow=0; while(bfs()){ for(int i=s;i<=t;i++) cur[i]=h[i]; flow+=dfs(s,INF); } return flow; } void bfsSol(){ memset(vis,0,sizeof(vis)); head=tail=1; q[tail++]=s; while(head!=tail){ int u=q[head++]; for(int i=h[u];i;i=e[i].ne) if(!vis[e[i].v]&&e[i].c>e[i].f) vis[e[i].v]=1,q[tail++]=e[i].v; } } bool check(double g){ cnt=0;memset(h,0,sizeof(h)); for(int i=1;i<=n;i++) ins(i,t,g); for(int i=1;i<=m;i++) ins(s,n+i,1),ins(n+i,u[i],INF),ins(n+i,v[i],INF); return m-dinic()>eps; } void solve(){ double l=1.0/n,r=m,eps=1.0/n/n; while(r-l>eps){ double mid=(l+r)/2.0;//printf("mid %lf %lf %lf ",l,r,mid); if(check(mid)) l=mid; else r=mid; } check(l); bfsSol(); int ans=0; for(int i=1;i<=n;i++) if(vis[i]) ans++; printf("%d ",ans); for(int i=1;i<=n;i++) if(vis[i]) printf("%d ",i); } int main(){ //freopen("in","r",stdin); n=read();m=read(); if(!m){printf("1 1");return 0;} s=0;t=n+m+1; for(int i=1;i<=m;i++) u[i]=read(),v[i]=read(); solve(); }