bzoj 3232: 圈地游戏【分数规划+最小割】
2018-10-16 07:16
351 查看
数组开小导致TTTTTLE……
是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0
这个最小割比较像最大权闭合子图,建图是s像所有点连流量为格子价值的边(相当于最大权闭合子图中的正权点),然后考虑边缘,两个相邻的格子,如果一个选一个不选那么中间这条边就有负的贡献,所以两个相邻的格子之间连两条边权为mid*边权的边,注意是两条,要互相连一下,然后所有边界上的点像t连边权为mid*边界边权的边,相当于假装外面还有一层点全标为t,然后跑最小割判断即可
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=105; const double eps=1e-6,inf=1e9; int n,m,h[N*N],cnt,s,t,id ,tot,le[N*N]; double a ,b ,c ,sm; struct qwe { int ne,to; double va; }e[N*N*N]; void add(int u,int v,double w) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; e[cnt].va=w; h[u]=cnt; } void ins(int u,int v,double w) { add(u,v,w); add(v,u,0); } bool bfs() { queue<int>q; memset(le,0,sizeof(le)); le[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=h[u];i;i=e[i].ne) if(e[i].va>eps&&!le[e[i].to]) { le[e[i].to]=le[u]+1; q.push(e[i].to); } } return le[t]; } double dfs(int u,double f) { if(u==t||!f) return f; double us=0; for(int i=h[u];i&&us<f;i=e[i].ne) if(e[i].va>eps&&le[e[i].to]==le[u]+1) { double t=dfs(e[i].to,min(e[i].va,f-us)); e[i].va-=t; e[i^1].va+=t; us+=t; } if(us<eps) le[u]=0; return us; } int dinic() { double re=0; while(bfs()) re+=dfs(s,inf); return re; } bool ok(double w) { memset(h,0,sizeof(h)); cnt=1,s=0,t=n*m+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ins(s,id[i][j],a[i][j]); for(int j=1;j<=m;j++) ins(id[1][j],t,w*b[0][j]),ins(id [j],t,w*b [j]); for(int i=1;i<=n;i++) ins(id[i][1],t,w*c[i][0]),ins(id[i][m],t,w*c[i][m]); for(int i=1;i<n;i++) for(int j=1;j<=m;j++) add(id[i][j],id[i+1][j],w*b[i][j]),add(id[i+1][j],id[i][j],w*b[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<m;j++) add(id[i][j],id[i][j+1],w*c[i][j]),add(id[i][j+1],id[i][j],w*c[i][j]); return sm-dinic()>eps; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%lf",&a[i][j]),id[i][j]=++tot,sm+=a[i][j]; for(int i=0;i<=n;i++) for(int j=1;j<=m;j++) scanf("%lf",&b[i][j]); for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) scanf("%lf",&c[i][j]); double l=0,r=n*m*100,ans=0; while(r-l>1e-5) { double mid=(l+r)/2; if(ok(mid)) l=mid,ans=mid; else r=mid; } printf("%.3f\n",ans); return 0; }
相关文章推荐
- 【BZOJ3232】圈地游戏 分数规划+最小割
- 【BZOJ 3232】圈地游戏 分数规划+最大权闭合图
- [置顶] bzoj3232: 圈地游戏 0-1分数规划
- bzoj3232: 圈地游戏 0-1分数规划
- bzoj 3232: 圈地游戏 01分数规划
- bzoj 3232: 圈地游戏 01分数规划
- 【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型
- BZOJ3232: 圈地游戏
- 【BZOJ1486】【HNOI2009】最小圈 分数规划 dfs判负环。
- BZOJ1486: [HNOI2009]最小圈 分数规划
- BZOJ 3232: 圈地游戏 分数规划+判负环
- BZOJ 1486: [HNOI2009]最小圈|分数规划
- [BZOJ2285][Sdoi2011]保密(01分数规划+最小割)
- BZOJ 1486: [HNOI2009]最小圈 分数规划
- [二分答案][网络流验证][BZOJ 3232]圈地游戏
- BZOJ3232: 圈地游戏
- bzoj 3232 01分数规划+最大权封闭子图判定
- bzoj1486 [HNOI2009]最小圈 【最小比例环 01分数规划】
- 【BZOJ1486】[HNOI2009]最小圈【SPFA判负环】【01分数规划】
- [省选前题目整理][BZOJ 1486][HNOI 2009]最小圈(01分数规划)