zoukankan      html  css  js  c++  java
  • bzoj 3232: 圈地游戏【分数规划+最小割】

    数组开小导致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[N][N],tot,le[N*N];
    double a[N][N],b[N][N],c[N][N],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[n][j],t,w*b[n][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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    AtCoder Beginner Contest 167
    AtCoder Beginner Contest 166
    AtCoder Beginner Contest 165
    AtCoder Beginner Contest 164
    AtCoder Beginner Contest 163
    AtCoder Beginner Contest 162
    AtCoder Beginner Contest 161
    AtCoder Beginner Contest 160
    AtCoder Beginner Contest 159
    自定义Mybatis自动生成代码规则
  • 原文地址:https://www.cnblogs.com/lokiii/p/9795805.html
Copyright © 2011-2022 走看看