洛谷 P4013 数字梯形问题
->题目链接
题解:
网络流。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #define N 4010 #define inf 1000000000 using namespace std; int a[N][N],head[N],dis[N],inq[N],fa[N],n,m,num,cnt,S,T; struct node { int u,v,pre,f,w; } e[N]; void add(int u,int v,int f,int w) { e[++cnt].u=u;e[cnt].v=v; e[cnt].f=f;e[cnt].w=w; e[cnt].pre=head[u];head[u]=cnt; e[++cnt].u=v;e[cnt].v=u; e[cnt].f=0;e[cnt].w=-w; e[cnt].pre=head[v];head[v]=cnt; } bool spfa() { for(int i=0; i<=T; i++) dis[i]=inf; queue<int> q; q.push(S); inq[S]=1; dis[S]=0; while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for(int i=head[u]; i; i=e[i].pre) if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w) { dis[e[i].v]=dis[u]+e[i].w; fa[e[i].v]=i; if(!inq[e[i].v]) { inq[e[i].v]=1; q.push(e[i].v); } } } return dis[T]!=inf; } void mincost() { int cost=0; while(spfa()) { int tmp=fa[T],x=inf; while(tmp) { int u=e[tmp].u; x=min(x,e[tmp].f); tmp=fa[e[tmp].u]; } tmp=fa[T]; while(tmp) { e[tmp].f-=x; e[tmp^1].f+=x; tmp=fa[e[tmp].u]; } cost+=x*dis[T]; } printf("%d\n",-cost); } int hao(int i,int j) { return (m*2+i-2)*(i-1)/2+j; } void build1() { cnt=1; memset(head,0,sizeof(head)); for(int i=1; i<=m; i++) add(S,i,1,-a[1][i]); for(int i=1; i<n; i++) for(int j=1; j<=m+i-1; j++) add(hao(i,j)+num,hao(i+1,j),1,-a[i+1][j]),add(hao(i,j)+num,hao(i+1,j+1),1,-a[i+1][j+1]); for(int i=1; i<=m+n-1; i++) add(hao(n,i)+num,T,1,0); for(int i=1; i<=n; i++) for(int j=1; j<=m+i-1; j++) add(hao(i,j),hao(i,j)+num,1,0); } void build2() { cnt=1; memset(head,0,sizeof(head)); for(int i=1; i<=m; i++) add(S,i,1,-a[1][i]); for(int i=1; i<=n; i++) for(int j=1; j<=m+i-1; j++) add(hao(i,j),hao(i+1,j),1,-a[i+1][j]),add(hao(i,j),hao(i+1,j+1),1,-a[i+1][j+1]); for(int i=1; i<=m+n-1; i++) add(hao(n,i),T,inf,0); } void build3() { cnt=1; memset(head,0,sizeof(head)); for(int i=1; i<=m; i++) add(S,i,1,-a[1][i]); for(int i=1; i<=n; i++) for(int j=1; j<=m+i-1; j++) add(hao(i,j),hao(i+1,j),inf,-a[i+1][j]),add(hao(i,j),hao(i+1,j+1),inf,-a[i+1][j+1]); for(int i=1; i<=m+n-1; i++) add(hao(n,i),T,inf,0); } int main() { scanf("%d%d",&m,&n); num=(m*2+n-1)*n/2; S=0; T=num*2+1; for(int i=1; i<=n; i++) for(int j=1; j<=m+i-1; j++) scanf("%d",&a[i][j]); build1(); mincost(); build2(); mincost(); build3(); mincost(); return 0; }
我走我的独木桥。