zoukankan      html  css  js  c++  java
  • 文理分科 BZOJ3894 & happiness BZOJ2127

    分析:

    最小割(一开始我没看出来...后来经过提点,大致理解...),不选则割的思想。

    我们先这样考虑,将和选理相关的和S相连,与选文相关的和T相连,如果没有第二问,那么建图就是简单的S连cnt,cnt连T,流量分别为对应的喜悦值,那么在这个图的基础上,考虑第二问,因为我们需要将所有不选的边割掉,那么,我们可以考虑新建两个点,一个连接S,流量为喜悦值,一个连接T,流量为喜悦值,那么将这两个节点连向相应的要求节点(比如两个人同时学理/文),流量为inf,这样,我们每次割掉一个S连向cnt的边的时候,必须将所有的S连向tot的边割掉,就相当于是题目的要求了,最后得到最小割,用总和减去最小割就好了。

    附上代码:(文理分科)

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <cstdlib>
    using namespace std;
    #define N 30005
    #define p(i,j) ((i-1)*m+j)
    #define inf 10000000
    #define S 0
    #define T 30004
    int head[N],cnt,dep[N],a[105][105],b[105][105],sum,n,m;
    struct node
    {
    	int to,next,val;
    }e[1000010];
    int dx[4]={0,1,-1,0};int dy[4]={1,0,0,-1};
    void add(int x,int y,int z){e[cnt].to=y;e[cnt].next=head[x];e[cnt].val=z;head[x]=cnt++;}
    void insert(int x,int y,int z){add(x,y,z);add(y,x,0);}
    int bfs()
    {
    	memset(dep,-1,sizeof(dep));
    	queue <int>q;q.push(S);dep[S]=1;
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		for(int i=head[x];i!=-1;i=e[i].next)
    		{
    			int to1=e[i].to;
    			if(dep[to1]==-1&&e[i].val)dep[to1]=dep[x]+1,q.push(to1);
    		}
    	}
    	return dep[T]==-1?0:1;
    }
    int dfs(int x,int maxf)
    {
    	if(x==T)return maxf;
    	int tflow=maxf,nowf;
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(dep[to1]==dep[x]+1&&e[i].val)
    		{
    			nowf=dfs(to1,min(e[i].val,tflow));
    			if(!nowf)dep[to1]=-1;
    			tflow-=nowf,e[i].val-=nowf,e[i^1].val+=nowf;
    			if(!tflow)break;
    		}
    	}
    	return maxf-tflow;
    }
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			int x;
    			scanf("%d",&x);sum+=x;
    			insert(S,p(i,j),x);
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			int x;
    			scanf("%d",&x);sum+=x;
    			insert(p(i,j),T,x);
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&a[i][j]);sum+=a[i][j];
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&b[i][j]);sum+=b[i][j];
    		}
    	}
    	int tot=n*m;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			tot+=2;
    			insert(S,tot-1,a[i][j]);insert(tot,T,b[i][j]);
    			insert(tot-1,p(i,j),inf);insert(p(i,j),tot,inf);
    			for(int k=0;k<4;k++)
    			{
    				int tx=dx[k]+i,ty=dy[k]+j;
    				if(tx>=1&&tx<=n&&ty<=m&&ty>=1)
    				{
    					insert(tot-1,p(tx,ty),inf);
    					insert(p(tx,ty),tot,inf);
    				}
    			}
    		}
    	}
    	int ans=0;
    	while(bfs())ans+=dfs(S,1<<30);
    	printf("%d
    ",sum-ans);
    	return 0;
    }
    

    附上代码:(happiness)

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <cstdlib>
    using namespace std;
    #define N 60005
    #define p(i,j) ((i-1)*m+j)
    #define inf 10000000
    #define S 0
    #define T 60004
    int head[N],cnt,dep[N],a[105][105],b[105][105],n,m;long long sum;
    struct node
    {
    	int to,next,val;
    }e[2000010];
    int dx[4]={0,1,-1,0};int dy[4]={1,0,0,-1};
    void add(int x,int y,int z){e[cnt].to=y;e[cnt].next=head[x];e[cnt].val=z;head[x]=cnt++;}
    void insert(int x,int y,int z){add(x,y,z);add(y,x,0);}
    int bfs()
    {
    	memset(dep,-1,sizeof(dep));
    	queue <int>q;q.push(S);dep[S]=1;
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		for(int i=head[x];i!=-1;i=e[i].next)
    		{
    			int to1=e[i].to;
    			if(dep[to1]==-1&&e[i].val)dep[to1]=dep[x]+1,q.push(to1);
    		}
    	}
    	return dep[T]==-1?0:1;
    }
    int dfs(int x,int maxf)
    {
    	if(x==T)return maxf;
    	int tflow=maxf,nowf;
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(dep[to1]==dep[x]+1&&e[i].val)
    		{
    			nowf=dfs(to1,min(e[i].val,tflow));
    			if(!nowf)dep[to1]=-1;
    			tflow-=nowf,e[i].val-=nowf,e[i^1].val+=nowf;
    			if(!tflow)break;
    		}
    	}
    	return maxf-tflow;
    }
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			int x;
    			scanf("%d",&x);sum+=x;
    			insert(S,p(i,j),x);
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			int x;
    			scanf("%d",&x);sum+=x;
    			insert(p(i,j),T,x);
    		}
    	}
    	for(int i=1;i<n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&a[i][j]);sum+=a[i][j];
    		}
    	}
    	for(int i=1;i<n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			scanf("%d",&b[i][j]);sum+=b[i][j];
    		}
    	}
    	int tot=n*m;
    	for(int i=1;i<n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			tot+=2;
    			insert(S,tot-1,a[i][j]);insert(tot,T,b[i][j]);
    			insert(tot-1,p(i,j),inf);insert(tot-1,p(i+1,j),inf);
    			insert(p(i,j),tot,inf);insert(p(i+1,j),tot,inf);
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<m;j++)
    		{
    			scanf("%d",&a[i][j]);sum+=a[i][j];
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<m;j++)
    		{
    			scanf("%d",&b[i][j]);sum+=b[i][j];
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<m;j++)
    		{
    			tot+=2;
    			insert(S,tot-1,a[i][j]);insert(tot,T,b[i][j]);
    			insert(tot-1,p(i,j),inf);insert(tot-1,p(i,j+1),inf);
    			insert(p(i,j),tot,inf);insert(p(i,j+1),tot,inf);
    		}
    	}
    	long long ans=0;
    	while(bfs())ans+=dfs(S,1<<30);
    	printf("%d
    ",sum-ans);
    	return 0;
    }
    

      

  • 相关阅读:
    ADV-拍卖
    poj1190生日蛋糕--DFS
    poj1562-DFS
    二叉树--先序中序遍历求后序遍历
    poj1753-Flip Game DFS解法
    Baby-gin
    OX Pattern
    C
    qi qiu

  • 原文地址:https://www.cnblogs.com/Winniechen/p/9128602.html
Copyright © 2011-2022 走看看