BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流
1
首先二分答案x,转化成判定是否存在一种方案,
使得所有人赢的次数都小于等于x。
然后对每个人和每场比赛建立二分图。
S->人i(x)
人->比赛(1)
比赛->T(1)。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 200050 #define M 800050 #define S (n+m+1) #define T (n+m+2) #define inf 0x3f3f3f3f int head[N],to[M],nxt[M],flow[M],cnt=1,n,m,xx[N],yy[N],ans[N]; int Q[N],l,r,dep[N]; inline void add(int u,int v,int f) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f; to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0; } bool bfs() { memset(dep,0,sizeof(dep)); dep[S]=1; l=r=0; Q[r++]=S; while(l<r) { int x=Q[l++],i; for(i=head[x];i;i=nxt[i]) { if(flow[i]&&!dep[to[i]]) { dep[to[i]]=dep[x]+1; if(to[i]==T) return 1; Q[r++]=to[i]; } } } return 0; } int dfs(int x,int mf) { if(x==T) return mf; int nf=0,i; for(i=head[x];i;i=nxt[i]) { if(dep[to[i]]==dep[x]+1&&flow[i]) { int tmp=dfs(to[i],min(mf-nf,flow[i])); if(!tmp) dep[to[i]]=0; nf+=tmp; flow[i]-=tmp; flow[i^1]+=tmp; if(nf==mf) break; } } return nf; } int dinic() { int ans=0; while(bfs()) ans+=dfs(S,inf); return ans; } bool check(int mid) { int i; memset(head,0,sizeof(head)); cnt=1; for(i=1;i<=n;i++) add(S,i,mid); for(i=1;i<=m;i++) add(xx[i],i+n,1),add(yy[i],i+n,1); for(i=1;i<=m;i++) add(i+n,T,1); return dinic()==m; } int main() { scanf("%d%d",&n,&m); int i,j; for(i=1;i<=m;i++) scanf("%d%d",&xx[i],&yy[i]); int l=1,r=m+1; while(l<r) { int mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } printf("%d\n",l); /*memset(head,0,sizeof(head)); cnt=1; for(i=1;i<=n;i++) add(S,i,l); for(i=1;i<=m;i++) add(xx[i],i+n,1),add(yy[i],i+n,1); for(i=1;i<=m;i++) add(i+n,T,1); int gay=dinic();gay++; for(i=1;i<=n;i++) { for(j=head[i];j;j=nxt[j]) { if(flow[j]==0&&to[j]!=S) ans[to[j]-n]=i; } } for(i=1;i<=m;i++) { printf("%d\n",ans[i]==xx[i]); }*/ }
BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流
原文:https://www.cnblogs.com/suika/p/9186863.html