数字梯形问题
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; }