bzoj 3894: 文理分科
Description
文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
果选择理科,将得到science[i][j]的满意值。
2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
心,所以会增加same_art[i][j]的满意值。
3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
科,则增加same_science[i]j[]的满意值。
小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
告诉他这个最大值。
Input
第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j];
Output
输出为一个整数,表示最大的满意值之和
Sample Input
3 4
13 2 4 13
7 13 8 12
18 17 0 5
8 13 15 4
11 3 8 11
11 18 6 5
1 2 3 4
4 2 3 2
3 1 0 4
3 2 3 2
0 2 2 1
0 2 4 4
13 2 4 13
7 13 8 12
18 17 0 5
8 13 15 4
11 3 8 11
11 18 6 5
1 2 3 4
4 2 3 2
3 1 0 4
3 2 3 2
0 2 2 1
0 2 4 4
Sample Output
152
HINT
样例说明
1表示选择文科,0表示选择理科,方案如下:
1 0 0 1
0 1 0 0
1 0 0 0
N,M<=100,读入数据均<=500
Source
一道很不错的最小割模型混杂题,画了好久才跑对QAQ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | // MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> #define RG register using namespace std; typedef long long ll; const int N=1000050; const int Inf=19260817; int gi(){ int x=0,flag=1; char ch=getchar(); while (ch< '0' ||ch> '9' ){ if (ch== '-' ) flag=-1;ch=getchar();} while (ch>= '0' &&ch<= '9' ) x=x*10+ch- '0' ,ch=getchar(); return x*flag; } int head[N],nxt[N],to[N],s[N],cnt=1,n,m; int a[550][550],b[550][550],c[550][550],d[550][550]; int id[550][550][3],tt,S,T,level[N],q[N*5],F,tot; int mx[5]={1,-1,0,0},my[5]={0,0,1,-1}; inline void Addedge(RG int x,RG int y,RG int z) { to[++cnt]=y,s[cnt]=z,nxt[cnt]=head[x],head[x]=cnt; } inline void lnk(RG int x,RG int y,RG int z){ Addedge(x,y,z),Addedge(y,x,0); } inline bool bfs(){ for (RG int i=S;i<=T;i++) level[i]=0; q[0]=S,level[S]=1; int t=0,sum=1; while (t<sum){ int x=q[t++]; if (x==T) return 1; for (RG int i=head[x];i;i=nxt[i]){ int y=to[i]; if (s[i]&&level[y]==0){ level[y]=level[x]+1; q[sum++]=y; } } } return 0; } inline int dfs(RG int x, int maxf){ if (x==T) return maxf; int ret=0; for (RG int i=head[x];i;i=nxt[i]){ int y=to[i],f=s[i]; if (level[y]==level[x]+1&&f){ int minn=min(f,maxf-ret); f=dfs(y,minn); s[i]-=f,s[i^1]+=f,ret+=f; if (ret==maxf) break ; } } if (!ret) level[x]=0; return ret; } inline void Dinic(){ while (bfs()) F+=dfs(S,Inf); } int main(){ n=gi(),m=gi(); for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++){ a[i][j]=gi(),tot+=a[i][j]; } for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++){ b[i][j]=gi();tot+=b[i][j]; } for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++){ c[i][j]=gi();tot+=c[i][j]; } for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++){ d[i][j]=gi();tot+=d[i][j]; } for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++) for ( int k=0;k<3;k++){ id[i][j][k]=++tt; } S=0,T=tt+1; for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++){ lnk(S,id[i][j][0],a[i][j]); lnk(id[i][j][0],T,b[i][j]); lnk(id[i][j][0],id[i][j][1],Inf); lnk(id[i][j][2],id[i][j][0],Inf); lnk(id[i][j][1],T,d[i][j]); lnk(S,id[i][j][2],c[i][j]); for ( int k=0;k<4;k++){ int x=i+mx[k],y=j+my[k]; if (1<=x&&x<=n&&1<=y&&y<=m){ lnk(id[x][y][0],id[i][j][1],Inf); lnk(id[i][j][2],id[x][y][0],Inf); } } } Dinic();printf( "%d\n" ,tot-F); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步