[最大流][二分]JZOJ 1259 牛棚
分析
发现牛棚对于奶牛有唯一对应关系,但每个牛棚有连接限制
不难想到网络流,以喜欢度作为权值
我们可以二分这个答案,然后枚举权值区间的左端l,则区间为[l,l+mid)
做最大流的时候加这个限制就好了
#include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int N=1e3+10; const int B=21; struct Pipe { int u,v,c,w,nx; }g[2*N*B+2*N+2*B]; int cnt=1,list[N+B],p[B],dis[N+B]; int n,b; int s,t,mid,ans,l; void Add(int u,int v,int w,int c) { g[++cnt]=(Pipe){u,v,c,w,list[u]};list[u]=cnt; g[++cnt]=(Pipe){v,u,0,0,list[v]};list[v]=cnt; } bool Spfa(int v0) { queue<int> q; while (!q.empty()) q.pop(); memset(dis,0,sizeof dis); q.push(v0);dis[v0]=1; while (!q.empty()) { int u=q.front();q.pop(); for (int i=list[u];i;i=g[i].nx) if (!dis[g[i].v]&&g[i].c&&(l<=g[i].w&&g[i].w<=l+mid-1||g[i].w==0)) { dis[g[i].v]=dis[u]+1; if (g[i].v==t) return 1; q.push(g[i].v); } } return 0; } int DFS(int u,int mf) { int flow,ret=0; if (u==t||mf==0) return mf; for (int i=list[u];i;i=g[i].nx) if (dis[u]+1==dis[g[i].v]&&(l<=g[i].w&&g[i].w<=l+mid-1||g[i].w==0)) { flow=DFS(g[i].v,min(g[i].c,mf)); g[i].c-=flow;g[i^1].c+=flow; ret+=flow; if (ret==mf) return ret; } return ret; } bool MCF() { int flow; for (l=1;l<=max(1,b-mid+1);l++) { flow=0; while (Spfa(s)) flow+=DFS(s,2147483647); for (int i=2;i<=cnt;i+=2) if (g[i].u==s) g[i].c=p[g[i].v],g[i^1].c=0; else g[i].c=1,g[i^1].c=0; if (flow==n) return 1; } } int main() { scanf("%d%d",&n,&b); s=0;t=n+b+1; for (int i=1;i<=n;i++) for (int j=1,c;j<=b;j++) { scanf("%d",&c); Add(c,i+b,j,1); } for (int i=1;i<=b;i++) scanf("%d",&p[i]),Add(s,i,0,p[i]); for (int i=1;i<=n;i++) Add(i+b,t,0,1); int l=1,r=20; while (l<=r) { mid=l+r>>1; if (MCF()) ans=mid,r=mid-1; else l=mid+1; } printf("%d",ans); }
在日渐沉没的世界里,我发现了你。