POJ 3155 Hard Life(最小割-最大密集サブマップ)

5294 ワード

タイトルリンク:http://poj.org/problem?id=3155
題意:n個の点m辺の無方向図を与える.最大密集サブマップの頂点数と各頂点番号を出力します.
構想:二分答えg,原図中の辺(u,v)連辺.sと各点は辺,各点と汇点は辺につながっている.d[i]は各点の度である.
#include <iostream>

#include <stdio.h>

#include <string.h>

#include <algorithm>

#include <cmath>

#include <vector>

#include <queue>

#include <set>

#include <stack>

#include <string>

#include <map>





#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>=0?(x):-(x))

#define i64 long long

#define u32 unsigned int

#define u64 unsigned long long

#define clr(x,y) memset(x,y,sizeof(x))

#define CLR(x) x.clear()

#define ph(x) push(x)

#define pb(x) push_back(x)

#define Len(x) x.length()

#define SZ(x) x.size()

#define PI acos(-1.0)

#define sqr(x) ((x)*(x))

#define MP(x,y) make_pair(x,y)

#define EPS 1e-9



#define FOR0(i,x) for(i=0;i<x;i++)

#define FOR1(i,x) for(i=1;i<=x;i++)

#define FOR(i,a,b) for(i=a;i<=b;i++)

#define FORL0(i,a) for(i=a;i>=0;i--)

#define FORL1(i,a) for(i=a;i>=1;i--)

#define FORL(i,a,b)for(i=a;i>=b;i--)

using namespace std;





void RD(int &x){scanf("%d",&x);}

void RD(u32 &x){scanf("%u",&x);}

void RD(double &x){scanf("%lf",&x);}

void RD(int &x,int &y){scanf("%d%d",&x,&y);}

void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}

void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}

void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}

void RD(int &x,int &y,int &z,int &t){scanf("%d%d%d%d",&x,&y,&z,&t);}

void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}

void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}

void RD(char &x){x=getchar();}

void RD(char *s){scanf("%s",s);}

void RD(string &s){cin>>s;}





void PR(int x) {printf("%d
",x);} void PR(int x,int y) {printf("%d %d
",x,y);} void PR(i64 x) {printf("%lld
",x);} void PR(u32 x) {printf("%u
",x);} void PR(double x) {printf("%.5lf
",x);} void PR(char x) {printf("%c
",x);} void PR(char *x) {printf("%s
",x);} void PR(string x) {cout<<x<<endl;} const int INF=1000000000; const int N=100005; struct Edge { int u,v; double cap,flow; int next; }; Edge edges[30000]; int head[105],e,visit[105]; int n,m,s,t; int a[1005],b[1005],d[105]; int num[105],h[105],curedge[105],pre[105]; int ans[105]; void add(int u,int v,double cap) { edges[e].u=u; edges[e].v=v; edges[e].cap=cap; edges[e].flow=0.0; edges[e].next=head[u]; head[u]=e++; } void Add(int u,int v,double cap) { add(u,v,cap); add(v,u,0.0); } void init(double mid) { int i; clr(head,-1); e=0; FOR1(i,m) { Add(a[i],b[i],1.0); Add(b[i],a[i],1.0); } FOR1(i,n) { Add(s,i,1.0*m); Add(i,t,m+2*mid-d[i]); } } double Maxflow(int s,int t) { double maxflow=0,d; int i,k,x,u; memset(num,0,sizeof(num)); memset(h,0,sizeof(h)); for(i=0;i<=t;i++) curedge[i]=head[i]; num[n]=n;u=s; while(h[s]<n) { if(u==t) { for(d=INF+1,i=s;i!=t;i=edges[curedge[i]].v)if(d>edges[curedge[i]].cap) k=i,d=edges[curedge[i]].cap; for(i=s;i!=t;i=edges[curedge[i]].v) { x=curedge[i]; edges[x].cap-=d; edges[x].flow+=d; edges[x^1].cap+=d; edges[x^1].flow-=d; } maxflow+=d;u=k; } for(i=curedge[u];i!=-1;i=edges[i].next)if(edges[i].cap>0&&h[u]==h[edges[i].v]+1) break; if(i!=-1) { curedge[u]=i; pre[edges[i].v]=u; u=edges[i].v; } else { if(0==--num[h[u]]) break; curedge[u]=head[u]; for(x=n,i=head[u];i!=-1;i=edges[i].next) if(edges[i].cap>0) x=min(x,h[edges[i].v]); h[u]=x+1;num[h[u]]++; if(u!=s) u=pre[u]; } } return maxflow; } void DFS(int u) { int i; visit[u]=1; if(u!=s) ans[++ans[0]]=u; for(i=head[u];i!=-1;i=edges[i].next) { if(edges[i].cap>1e-8&&!visit[edges[i].v]) { DFS(edges[i].v); } } } double calMaxDensity(int s,int t) { double low,high,mid,flow; low=0.0;high=1.0*m; while(high-low>=1.0/n/n) { mid=(low+high)/2; init(mid); flow=Maxflow(s,t); flow=(1.0*m*n-flow)/2; if(flow>1e-8) low=mid; else high=mid; } init(low); Maxflow(s,t);clr(visit,0); ans[0]=0;DFS(s); sort(ans+1,ans+ans[0]+1); return low; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { int i; clr(d,0); FOR1(i,m) { RD(a[i],b[i]); d[a[i]]++; d[b[i]]++; } if(!m) { puts("1"); puts("1"); continue; } s=0;t=n+1; calMaxDensity(s,t); PR(ans[0]); FOR1(i,ans[0]) PR(ans[i]); } return 0; }