https://loj.ac/problem/6010
拆点最大费用最大流
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
const int inf = 0x3f3f3f3f3f;
int head[maxn*maxn];
int a[maxn][maxn];
struct edge{
int v,nex,w,c;
}e[maxn*maxn*100];
int tot;
void addedge(int u,int v,int w,int c){
e[tot] = (edge){v,head[u],w,c};
head[u] = tot++;
e[tot] = (edge){u,head[v],0,-c};
head[v] = tot++;
}
int vis[maxn*maxn];
int dis[maxn*maxn];
int pre[maxn*maxn];
bool spfa(int S,int T){
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
queue<int> q;
q.push(S);
vis[S] = 1;
dis[S] = 0;
while(!q.empty()){
int now = q.front();
q.pop();
vis[now] = 0;
for(int i=head[now];i!=-1;i=e[i].nex){
int v = e[i].v;
int w = e[i].w;
int c = e[i].c;
if(w>0 && dis[v]>dis[now]+c){
dis[v] = dis[now]+c;
pre[v] = i;
if(vis[v]==0) {
vis[v] = 1;
q.push(v);
}
}
}
}
if(dis[T]==0x3f3f3f3f) return false;
return true;
}
int ed(int S,int T,int &maxflow){
int flow = 0x3f3f3f3f;
int p;
for(int i=T;i!=S;i=e[p^1].v){
p = pre[i];
flow = min(flow,e[p].w);
}
int ans = 0;
for(int i=T;i!=S;i=e[p^1].v){
p = pre[i];
ans+=flow*e[p].c;
e[p].w-=flow;
e[p^1].w+=flow;
}
maxflow+=flow;
return ans;
}
int m,n;
int P(int x,int y){
return x*(n+m)+y;
}
int Q(int x,int y){
return x*(n+m)+y+(n+m)*n;
}
void solve1(){
int S = maxn*maxn-3;
int T1 = S+1;
int T2 = T1+1;
for(int i=0;i<n;i++){
for(int j=0;j<m+i;j++){
addedge(P(i,j),Q(i,j),1,0);
if(i==0) {
addedge(S,P(i,j),inf,-a[i][j]);
}else{
addedge(Q(i-1,j),P(i,j),1,-a[i][j]);
if(j!=0) {
addedge(Q(i-1,j-1),P(i,j),1,-a[i][j]);
}
}
}
}
for(int j=0;j<m+n;j++){
addedge(Q(n-1,j),T1,1,0);
}
addedge(T1,T2,m,0);
int maxflow = 0;
int ans = 0;
while(spfa(S,T2)){
ans+=ed(S,T2,maxflow);
}
printf("%d\n",-ans);
}
void solve2(){
int S = 41*41;
int T1 = S+1;
int T2 = T1+1;
for(int i=0;i<n;i++){
for(int j=0;j<m+i;j++){
addedge(P(i,j),Q(i,j),inf,0);
if(i==0) {
addedge(S,P(i,j),1,-a[i][j]);
}else{
addedge(Q(i-1,j),P(i,j),1,-a[i][j]);
if(j!=0) {
addedge(Q(i-1,j-1),P(i,j),1,-a[i][j]);
}
}
}
}
for(int j=0;j<m+n;j++){
addedge(Q(n-1,j),T1,inf,0);
}
addedge(T1,T2,m,0);
int maxflow = 0;
int ans = 0;
while(spfa(S,T2)){
ans+=ed(S,T2,maxflow);
}
printf("%d\n",-ans);
}
void solve3(){
int S = 41*41;
int T1 = S+1;
int T2 = T1+1;
for(int i=0;i<n;i++){
for(int j=0;j<m+i;j++){
addedge(P(i,j),Q(i,j),inf,0);
if(i==0) {
addedge(S,P(i,j),1,-a[i][j]);
}else{
addedge(Q(i-1,j),P(i,j),inf,-a[i][j]);
if(j!=0) {
addedge(Q(i-1,j-1),P(i,j),inf,-a[i][j]);
}
}
}
}
for(int j=0;j<m+n;j++){
addedge(Q(n-1,j),T1,inf,0);
}
addedge(T1,T2,m,0);
int maxflow = 0;
int ans = 0;
while(spfa(S,T2)){
ans+=ed(S,T2,maxflow);
}
printf("%d\n",-ans);
}
int main()
{
memset(head,-1,sizeof(head));
tot = 0;
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++){
for(int j=0;j<m+i;j++){
scanf("%d",&a[i][j]);
}
}
solve1();
memset(head,-1,sizeof(head));
tot = 0;
solve2();
memset(head,-1,sizeof(head));
tot = 0;
solve3();
return 0;
}