「luogu - P4313」文理分科 Mincut
link。
Pretty nice practice for the min-cut trick.
Starting out we eliminate the constraint that if five students in a edge-connected component alternatively choose exactly the same learning branch they get an extra contribution to the answer, and easily we can work it out with the following way to build a network and run a max-flow algorithm:
- Connect the source with each student and set the capacities of arcs as the number of euphorias the student would get if he or she chooses Arts.
- Connect each student with the sink and set capacities of arcs as the number of euphorias the student would get if he or she chooses Science.
Considering how to deal with the extra contributions, we simply shrink the four neighboring students and the student himself or herself into one point and connect the source with this taken the extra contributions (for choosing Arts) as the capacities. Additionally, connect the point with the four neighboring students taken \(+\infty\) as the capacities. So do we process ones who choose Science.
Just as the picture via @jun头吉吉 goes.
#include
using namespace std;
const int INF=0x3f3f3f3f;
template struct Net {
const int n;
struct Arc {
int to; size_t rev; Kap cap,flow;
};
vector> e;
vector iter,lev;
queue> q;
Net(int n):n(n),e(n),iter(n),lev(n) {}
void line(int one,int ano,Kap ca) {
one--; ano--;
assert(0<=one && one::max()); }
bool Getlayer(int s,int t) {
lev.assign(n,0); q.push(s); lev[s]=1;
while(q.size()) {
int now=q.front(); q.pop();
for(int i=0; ie[now][i].flow) lev[y]=lev[now]+1,q.push(y);
}
}
return lev[t];
}
Kap Augment(int now,Kap up,int t) {
if(now==t) return up;
Kap rlow=0;
for(int& i=iter[now]; ie[now][i].flow) {
Kap f=Augment(y,min(up-rlow,e[now][i].cap-e[now][i].flow),t);
e[now][i].flow+=f; e[y][e[now][i].rev].flow-=f; rlow+=f;
}
}
if(up==rlow) lev[now]=0;
return rlow;
}
Kap dinitz(int s,int t,const Kap INF) {
assert(0<=s && s=1 && x<=n && y>=1 && y<=m; }
int getID(int x,int y) { return (x-1)*m+y; }
int artify(int x) { return x+n*m; }
int sciencify(int x) { return x+n*m*2; }
signed main() {
scanf("%d %d",&n,&m);
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) scanf("%d",&exta[i][j]),sum+=exta[i][j];
}
for(int i=1; i<=n; ++i) {
for(int j=1; j<=m; ++j) scanf("%d",&extb[i][j]),sum+=extb[i][j];
}
Net net(n*m*3+2); S=n*m*3+1; T=n*m*3+2;
for(int i=1; i<=n; ++i) {
for(int j=1; j<=m; ++j) {
net.line(S,getID(i,j),a[i][j]);
net.line(getID(i,j),T,b[i][j]);
net.line(S,artify(getID(i,j)),exta[i][j]);
net.line(artify(getID(i,j)),getID(i,j),INF);
net.line(getID(i,j),sciencify(getID(i,j)),INF);
net.line(sciencify(getID(i,j)),T,extb[i][j]);
if(valid(i+1,j)) {
net.line(artify(getID(i,j)),getID(i+1,j),INF);
net.line(getID(i+1,j),sciencify(getID(i,j)),INF);
}
if(valid(i,j+1)) {
net.line(artify(getID(i,j)),getID(i,j+1),INF);
net.line(getID(i,j+1),sciencify(getID(i,j)),INF);
}
if(valid(i-1,j)) {
net.line(artify(getID(i,j)),getID(i-1,j),INF);
net.line(getID(i-1,j),sciencify(getID(i,j)),INF);
}
if(valid(i,j-1)) {
net.line(artify(getID(i,j)),getID(i,j-1),INF);
net.line(getID(i,j-1),sciencify(getID(i,j)),INF);
}
}
}
printf("%d\n",sum-net.dinitz(S,T));
return 0;
}