zoukankan      html  css  js  c++  java
  • BZOJ2132 圈地计划

    传送~

    来自y_immortal学长的网络流推荐2333

    建模比较神仙qwq

    首先可以建立最小割模型 ->二选一

    就是我们处理不同的贡献不好处理 那么我们考虑怎么把它变成相同的贡献

    对于原图我们进行黑白染色 然后如果一个点属于T集我们让它反色就可以做到相同的有贡献

    那么很明显这个贡献是双向的 对于两个点之间的贡献是相加的

    所以我们这样做最小割就可以辣~

    代码。

    //Love and Freedom.
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define inf 20021225
    #define ll long long
    #define M 200000
    #define N 30000
    using namespace std;
    
    struct edge{int to,lt,f;}e[M];
    int in[N],cnt=1,dep[N];
    int s,t;
    void add(int x,int y,int f)
    {
    	e[++cnt].to = y; e[cnt].lt = in[x]; e[cnt].f = f; in[x] = cnt;
    	e[++cnt].to = x; e[cnt].lt = in[y]; e[cnt].f = 0; in[y] = cnt;
    }
    queue<int> q;
    bool bfs()
    {
    	while(!q.empty())	q.pop();
    	memset(dep,0,sizeof(dep));
    	dep[s] = 1; q.push(s);
    	while(!q.empty())
    	{
    		int x = q.front(); q.pop();
    		for(int i=in[x];i;i=e[i].lt)
    		{
    			int y = e[i].to;
    			if(!dep[y] && e[i].f)
    			{
    				dep[y] = dep[x]+1;	q.push(y);
    				if(dep[t])	return true;
    			}
    		}
    	}
    	return false;
    }
    
    int dfs(int x,int f)
    {
    	if(x==t||!f)	return f;
    	int cur = f;
    	for(int i=in[x];i;i=e[i].lt)
    	{
    		int y = e[i].to;
    		if(dep[y] == dep[x]+1 && e[i].f)
    		{
    			int flow = dfs(y,min(cur,e[i].f));
    			e[i].f -= flow; e[i^1].f += flow;
    			cur -= flow; if(cur==0)	return f;
    		}
    	}
    	dep[x] = -1;
    	return f-cur;
    }
    
    int dinic()
    {
    	int ans = 0;
    	while(bfs())	ans+=dfs(s,inf);
    	return ans;
    }
    int n,m;
    int id(int x,int y)
    {
    	return (x-1)*m + y;
    }
    int a[101][101];
    int b[101][101];
    int c[101][101];
    int xx[4] = {0,0,1,-1};
    int yy[4] = {1,-1,0,0};
    int main()
    {
    	int fin = 0;
    	scanf("%d%d",&n,&m);
    	s = n*m*2; t = s+1;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&a[i][j]);
    			if((i+j)&1)	add(s,id(i,j),a[i][j]);
    			else	add(id(i,j),t,a[i][j]);
    			fin+=a[i][j];
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&b[i][j]);
    			if((i+j)&1)	add(id(i,j),t,b[i][j]);
    			else	add(s,id(i,j),b[i][j]);
    			fin+=b[i][j];
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			scanf("%d",&c[i][j]);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			for(int k=0;k<4;k++)
    			{
    				int x = i+xx[k], y = j+yy[k];
    				if(x<1||y<1||x>n||y>m)	continue;
    				int val = c[i][j] + c[x][y];
    				add(id(i,j),id(x,y),val);
    				fin+=c[i][j];
    			}
    	printf("%d
    ",fin-dinic());
    	return 0;
    }
  • 相关阅读:
    Python 正则表达式(分组)
    django 笔记
    Java代理和动态代理机制分析和应用
    Chrome浏览器如何调试移动端网页信息
    【数据分析】Excle中安装数据分析工具
    【BigData】Java基础_socket编程中使用多线程
    【BigData】Java基础_多线程
    【BigData】Java基础_socket编程
    财务报表之利润表
    资产负债表的会计恒等式
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321871.html
Copyright © 2011-2022 走看看