bzoj2245: [SDOI2011]工作安排
费用流。
这道题的模型比较明显,拆点也是很容易看出来的。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1000 + 10; const int maxm = 500000 + 10; const int inf = 0x3f3f3f3f; int g[maxn],v[maxm],f[maxm],c[maxm],next[maxm],eid; int idn[maxn],idm[maxn]; int a[maxn][5]; int n,m,S,T,vid,u; int d[maxn],pre[maxn]; int q[maxn],l,r; bool inque[maxn]; void addedge(int a,int b,int F,int C) { v[eid]=b; f[eid]=F; c[eid]=C; next[eid]=g[a]; g[a]=eid++; v[eid]=a; f[eid]=0; c[eid]=-C; next[eid]=g[b]; g[b]=eid++; } void build() { memset(g,-1,sizeof(g)); scanf("%d%d",&n,&m); S=1; T=2; vid=2; for(int i=1,t;i<=m;i++) { idm[i]=++vid; scanf("%d",&t); addedge(S,idm[i],t,0); } for(int i=1;i<=n;i++) { idn[i]=++vid; for(int j=1,t;j<=m;j++) { scanf("%d",&t); if(t==1) addedge(idm[j],idn[i],inf,0); } } for(int i=1,t;i<=n;i++) { scanf("%d",&t); for(int j=1;j<=t;j++) scanf("%d",&a[j][1]); a[t+1][1]=inf; for(int j=1;j<=t+1;j++) scanf("%d",&a[j][2]); for(int j=1;j<=t+1;j++) addedge(idn[i],T,a[j][1]-a[j-1][1],a[j][2]); } } bool SPFA() { memset(d,0xe3f,sizeof(d)); d[S]=0; l=r=0; inque[q[r++]=S]=1; while(l<r) { inque[u=q[l++]]=0; for(int i=g[u];~i;i=next[i]) if(f[i] && d[v[i]]>d[u]+c[i]) { d[v[i]]=d[u]+c[i]; pre[v[i]]=i; if(!inque[v[i]]) { inque[q[r++]=v[i]]=1; } } } return d[T]<inf; } int augment() { int aug=inf,res=0; for(int i=T;i!=S;i=v[pre[i]^1]) { aug=min(aug,f[pre[i]]); } for(int i=T;i!=S;i=v[pre[i]^1]) { f[pre[i]]-=aug; f[pre[i]^1]+=aug; res+=c[pre[i]]*aug; } return res; } void solve() { long long res=0; while(SPFA()) res+=augment(); printf("%lld\n",res); } int main() { build(); solve(); return 0; }