P3440 [POI2006]SZK-Schools(费用流)
Posted kafuuchino
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3440 [POI2006]SZK-Schools(费用流)相关的知识,希望对你有一定的参考价值。
每所学校$i$开一个点,$link(S,i,1,0)$
每个编号$j$开一个点,$link(i,T,1,0)$
蓝后学校向编号连边,$link(i,j,1,val)$
最后跑一遍费用流
如果没有满流就是$NIE$
否则就是最小代价了
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; inline int Abs(int a){return a<0?-a:a;} #define N 5005 #define W 500005 int n,m,S,T,tF,tC,a[N],d[N],p[N]; bool inh[N]; int cnt=1,hd[N],nxt[W],ed[N],poi[W],val[W],cst[W]; queue <int> h; inline void adde(int x,int y,int v1,int v2){ nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt, ed[x]=cnt, poi[cnt]=y, val[cnt]=v1, cst[cnt]=v2; } inline void link(int x,int y,int v1,int v2){adde(x,y,v1,v2),adde(y,x,0,-v2);} bool bfs(){ memset(d,63,sizeof(d)); int inf=d[0]; h.push(S); a[S]=inf; d[S]=0; inh[S]=1; while(!h.empty()){ int x=h.front(); h.pop(); inh[x]=0; for(int i=hd[x];i;i=nxt[i]){ int to=poi[i]; if(val[i]>0&&d[to]>d[x]+cst[i]){ d[to]=d[x]+cst[i]; p[to]=i; a[to]=min(a[x],val[i]); if(!inh[to]) h.push(to),inh[to]=1; } } }if(d[T]==inf) return 0; tF+=a[T]; tC+=a[T]*d[T]; for(int i=T;i!=S;i=poi[p[i]^1]) val[p[i]]-=a[T],val[p[i]^1]+=a[T]; return 1; } int main(){ scanf("%d",&n); int id,l,r,c; S=n*2+1; T=S+1; for(int i=1;i<=n;++i) link(S,i,1,0); for(int i=n+1;i<=n+n;++i) link(i,T,1,0); for(int i=1;i<=n;++i){ scanf("%d%d%d%d",&id,&l,&r,&c); for(int j=l;j<=r;++j) link(i,j+n,1,c*Abs(id-j)); }while(bfs()); if(tF<n) puts("NIE"); else printf("%d",tC); return 0; }
以上是关于P3440 [POI2006]SZK-Schools(费用流)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1520[POI2006]Szk-Schools KM算法
bzoj 1513 [POI2006]Tet-Tetris 3D(二维线段树)