zoukankan      html  css  js  c++  java
  • 洛谷P2774 方格取数问题

    题目大意:

    有一个(m*n)的网格图,每个格子有一个权值,要求选了当前格子后不能选择与当前格子相邻的四个格子,求选择的最大权值和

    最小割构造模型,又有点类似最大闭合权子图的思想

    先将所有格子的权值加起来

    然后将格子黑白染色,将黑色格子与(S)相连,白色格子与(T)相连,容量为点权。

    然后将黑色能影响到的白色格子连一条(inf)

    根据最大闭合权子图的思想,答案即为总权值减去最小割

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;
    	char ch;
    	for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    	if(ch=='-') f=0,ch=getchar();
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    const int inf=0x7f7f7f7f;
    int n,m,st,ed,ret,sum,tot;
    int id[110][110];
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    int head[10010],cur[10010],d[10010],cnt=1;
    struct point
    {
    	int nxt,to,val;
    }a[200010];
    inline void add(int x,int y,int z)
    {
    	a[++cnt].nxt=head[x];
    	a[cnt].to=y;
    	a[cnt].val=z;
    	head[x]=cnt;
    }
    queue<int> q;
    inline bool bfs()
    {
    	for(int i=1;i<=n*m+2;++i)
    	{
    		cur[i]=head[i];
    		d[i]=0;
    	}
    	q.push(st);d[st]=1;
    	while(!q.empty())
    	{
    		int now=q.front();
    		q.pop();
    		for(int i=head[now];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			if(!d[t]&&a[i].val)
    			{
    				d[t]=d[now]+1;
    				q.push(t);
    			}
    		}
    	}
    	return d[ed];
    }
    inline int dfs(int now,int c)
    {
    	if(now==ed||!c) return c;
    	int ret=c,f;
    	for(int i=cur[now];i;i=a[i].nxt)
    	{
    		cur[now]=i;
    		int t=a[i].to;
    		if(d[t]==d[now]+1)
    		{
    			f=dfs(t,min(a[i].val,ret));
    			if(!f) continue;
    			a[i].val-=f;
    			a[i^1].val+=f;
    			ret-=f;
    			if(!ret) return c;
    		}
    	}
    	if(c==ret) d[now]=0;
    	return c-ret;
    }
    inline int dinic()
    {
    	while(bfs()) ret+=dfs(st,inf);
    	return ret;
    }
    signed main()//最大独立点权集=最点权-最小点权覆盖(最小割)
    {
    	n=read(),m=read();
    	st=n*m+1,ed=n*m+2;
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			id[i][j]=++tot;
    	for(int x,i=1;i<=n;++i)
    	{
    		for(int j=1;j<=m;++j)
    		{
    			x=read();
    			sum+=x;
    			if(((i+j)&1)==1)//二分图染色,(i+j)&1==1为黑,源点连黑,汇点连白
    			{
    				add(st,id[i][j],x),add(id[i][j],st,0);
    				for(int k=0;k<4;++k)//黑向影响到的白连Inf边
    				{
    					int tx=i+dx[k],ty=j+dy[k];
    					add(id[i][j],id[tx][ty],inf);
    					add(id[tx][ty],id[i][j],0);
    				}
    			}
    			else add(id[i][j],ed,x),add(ed,id[i][j],0);
    		}
    	}
    	printf("%d
    ",sum-dinic());
    return 0;
    }
    
  • 相关阅读:
    Logistic Regression
    如何把日期格式化为指定格式?
    JavaScript的自调用函数
    elementui 在原生方法参数里,添加参数
    原生js实现随着滚动条滚动,导航会自动切换的效果
    微信小程序-canvas绘制文字实现自动换行
    visual studio 和 sql server 的激活密钥序列号
    跨多个服务器访问不同数据库的表的方法
    数据库面试中常问的几个问题
    聚集索引和非聚集索引的区别
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12095119.html
Copyright © 2011-2022 走看看