poj3155 Hard Life 【最大密度图 01分数规划】
2016-08-01 20:48
351 查看
链接:http://poj.org/problem?id=3155
题意:给你一个图,n个点,m条边,现在要你找到一个子图,求子图中的边数与点数的比值最大。
分析:《最小割模型在信息学竞赛中的应用》(胡伯涛著)中的论问题。
01分数规划套路。。:R=sigma(e)/sigma(v) 设 F(L)=sigma(e)-L*sigma(v),但是我们二分出L后并不知道取哪些边。但是我们知道取了(u,v)这条边,那么我们就一定要取u和v这两点,这就可以转换成求最大权闭合子图。我们可以将边和点看成同一种点,边连向u,v无穷大的边,s到边为1,u,v到t为L。F(L)=m-最小割。
代码:最好理解的建边,没优化的。。
题意:给你一个图,n个点,m条边,现在要你找到一个子图,求子图中的边数与点数的比值最大。
分析:《最小割模型在信息学竞赛中的应用》(胡伯涛著)中的论问题。
01分数规划套路。。:R=sigma(e)/sigma(v) 设 F(L)=sigma(e)-L*sigma(v),但是我们二分出L后并不知道取哪些边。但是我们知道取了(u,v)这条边,那么我们就一定要取u和v这两点,这就可以转换成求最大权闭合子图。我们可以将边和点看成同一种点,边连向u,v无穷大的边,s到边为1,u,v到t为L。F(L)=m-最小割。
代码:最好理解的建边,没优化的。。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 2010 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1)) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; const double eps=1e-5; struct edge { int v,next; double w; } e[Mm]; int deep[Mn]; int head[Mn]; int cur[Mn]; int N,tot; void addedge(int u,int v,double w) { e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } queue<int> q; bool bfs(int st,int en) { while(!q.empty()) q.pop(); CLR(deep,-1); q.push(st); deep[st]=0; while(!q.empty()) { int u=q.front(); q.pop(); if(u==en) return true; for(int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].v; double w=e[i].w; if(w>0&&deep[v]==-1) { deep[v]=deep[u]+1; q.push(v); } } } return false; } double dfs(int u,double sum,int en) { if(u==en) return sum; double a=0,us=0; for(int &i=cur[u]; i!=-1; i=e[i].next) { if(deep[e[i].v]==deep[u]+1) { a=sum-us; a=dfs(e[i].v,min(a,e[i].w),en); e[i].w-=a; e[i^1].w+=a; if(e[i].w) cur[u]=i; us+=a; if(us==sum) return sum; } } if(!us) deep[u]=-1; return us; } double dinic(int st,int en) { double ans=0; while(bfs(st,en)) { CPY(cur,head); ans+=dfs(st,INF,en); } return ans; } int n,m; int u[Mn],v[Mn]; void init() { tot=0; CLR(head,-1); } bool check(double x) { init(); int cnt=0; int s=0,t=n+m+1; for(int i=1;i<=m;i++) { cnt++; addedge(s,n+cnt,1); addedge(n+cnt,s,0); addedge(n+cnt,u[i],INF); addedge(u[i],n+cnt,0); addedge(n+cnt,v[i],INF); addedge(v[i],n+cnt,0); } for(int i=1;i<=n;i++) { addedge(i,t,x); addedge(t,i,0); } double ans=1.0*m-dinic(s,t); if(fabs(ans)>eps) return true; return false; } int vis[Mn]; int num=0; void findv(int u) { vis[u]=1; if(u<=n&&u>=1) num++; for(int i=head[u];~i;i=e[i].next) { int v=e[i].v; if(!vis[v]&&e[i].w>0) findv(v); } } int main() { scanf("%d%d",&n,&m); if(!m) { printf("1\n1\n"); return 0; } for(int i=1;i<=m;i++) { scanf("%d%d",&u[i],&v[i]); } double l=1.0/n,r=m; while(fabs(r-l)>eps) { double mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } check(l); findv(0); printf("%d\n",num); for(int i=1;i<=n;i++){ if(vis[i]) printf("%d\n",i); } return 0; }
相关文章推荐
- poj 3155 Hard Life 【最大密度子图】 【0-1分数规划 + 最小割】
- POJ3155_Hard Life_二分求解分数规划||最大权闭合图
- POJ 3621 Sightseeing Cows 最大密度环 01分数规划
- poj 3155 Hard Life(最大密度子图,01分数规划)
- 【01分数规划】最大密度子图
- bzoj 1312: Hard Life 01分数规划+网络流
- poj 3155 Hard Life(01分数规划+最大流--最大密度子图)
- POJ-3155-Hard Life(最大密度子图)(01分数规划+最小割)
- [最大密度子图 最小割] BZOJ 1312 Neerc2006 Hard Life
- BZOJ 4501: 旅行 01分数规划 最大权闭合子图
- [POJ3155]Hard Life(01分数规划)
- zoj 2676 Network Wars(01分数规划+最大流)
- POJ Hard Life (最大密度子图)
- [Sdoi2017]新生舞会 [01分数规划 二分图最大权匹配]
- poj3621 Sightseeing Cows 【最大比例环 01分数规划】
- poj 3155 01规划->最大密度密度子图->最大流
- poj 3155(Hard Life)分数规划/最大密度子图
- 最大密集子图(01分数规划+二分+最小割)POJ3155
- POJ - 3111 K Best 平均值最大(01分数规划)
- 最大密集子图(01分数规划+二分+最小割)POJ3155