分析:
最小割(一开始我没看出来...后来经过提点,大致理解...),不选则割的思想。
我们先这样考虑,将和选理相关的和S相连,与选文相关的和T相连,如果没有第二问,那么建图就是简单的S连cnt,cnt连T,流量分别为对应的喜悦值,那么在这个图的基础上,考虑第二问,因为我们需要将所有不选的边割掉,那么,我们可以考虑新建两个点,一个连接S,流量为喜悦值,一个连接T,流量为喜悦值,那么将这两个节点连向相应的要求节点(比如两个人同时学理/文),流量为inf,这样,我们每次割掉一个S连向cnt的边的时候,必须将所有的S连向tot的边割掉,就相当于是题目的要求了,最后得到最小割,用总和减去最小割就好了。
附上代码:(文理分科)
#include#include #include #include #include #include #include using namespace std;#define N 30005#define p(i,j) ((i-1)*m+j)#define inf 10000000#define S 0#define T 30004int 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 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\n",sum-ans); return 0;}
附上代码:(happiness)
#include#include #include #include #include #include #include using namespace std;#define N 60005#define p(i,j) ((i-1)*m+j)#define inf 10000000#define S 0#define T 60004int 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 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