洛谷P4013 数字梯形问题 费用流
Code:
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int maxn=10000; const int INF=100000+666; typedef long long ll; int A[700][700]; int idx[700][700]; int s,t,n,M,N; struct Edge{ int from,to,cap,cost; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),cost(f){} }; struct MCMF{ vector<Edge>edges; vector<int>G[maxn]; int d[maxn],inq[maxn],a[maxn],flow2[maxn]; queue<int>Q; ll ans=0; int flow=0; void init(){ for(int i=0;i<maxn;++i)G[i].clear(); edges.clear(); ans=0; } void addedge(int u,int v,int c,int f){ edges.push_back(Edge(u,v,c,f)); //正向弧 edges.push_back(Edge(v,u,0,-f)); //反向弧 int m=edges.size(); G[u].push_back(m-2); G[v].push_back(m-1); } int SPFA(){ for(int i=0;i<=n;++i)d[i]=INF,flow2[i]=INF; memset(inq,0,sizeof(inq));int f=INF; d[s]=0,inq[s]=1;Q.push(s); while(!Q.empty()){ int u=Q.front();Q.pop();inq[u]=0; int sz=G[u].size(); for(int i=0;i<sz;++i){ Edge e=edges[G[u][i]]; if(e.cap>0&&d[e.to]>d[u]+e.cost){ a[e.to]=G[u][i]; d[e.to]=d[u]+e.cost; flow2[e.to]=min(flow2[u],e.cap); if(!inq[e.to]){inq[e.to]=1;Q.push(e.to);} } } } if(d[t]==INF)return 0; f=flow2[t]; flow+=f; int u=edges[a[t]].from; edges[a[t]].cap-=f; edges[a[t]^1].cap+=f; while(u!=s){ edges[a[u]].cap-=f; edges[a[u]^1].cap+=f; u=edges[a[u]].from; } ans+=(ll)(d[t]*f); return 1; } ll getcost(){ while(SPFA()); return -ans; } }op; void build(int cap_point,int cap_edge,int c2){ for(int i=1;i<=M;++i)op.addedge(s,idx[1][i],1,0); for(int i=1;i<=N-1;++i) for(int j=1;j<=M+i-1;++j) { op.addedge(idx[i][j],idx[i][j]+1,cap_point,-A[i][j]); op.addedge(idx[i][j]+1,idx[i+1][j],cap_edge,0); op.addedge(idx[i][j]+1,idx[i+1][j+1],cap_edge,0); } for(int i=1;i<=M+N-1;++i)op.addedge(idx[N][i],idx[N][i]+1,cap_point,-A[N][i]); for(int i=1;i<=M+N-1;++i)op.addedge(idx[N][i]+1,t,c2,0); } int main() { int cnt=1; scanf("%d%d",&M,&N); for(int i=1;i<=N;++i) for(int j=1;j<=M+i-1;++j){ scanf("%d",&A[i][j]); idx[i][j]=cnt,cnt+=2; } s=0,t=cnt,n=cnt; build(1,1,1); printf("%lld\n",op.getcost()); op.init(); build(INF,1,INF); printf("%lld\n",op.getcost()); op.init(); build(INF,INF,INF); printf("%lld",op.getcost()); return 0; }