洛谷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;
}

浙公网安备 33010602011771号