BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流
BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流
Description
Dicing 是一个两人玩的游戏,这个游戏在Byteotia非常流行. 甚至人们专门成立了这个游戏的一个俱乐部. 俱乐部的人时常在一起玩这个游戏然后评选出玩得最好的人.现在有一个非常不走运的家伙,他想成为那个玩的最好的人,他现在知道了所有比赛的安排,他想知道,在最好的情况下,他最少只需要赢几场就可以赢得冠军,即他想知道比赛以后赢的最多的那个家伙最少会赢多少场.
Input
第一行两个整数n 和 m, 1 <= n <= 10 000, 0 <= m <= 10 000; n 表示一共有多少个参赛者, m 表示有多少场比赛. 选手从1 到 n编号. 接下来m 行每行两个整数表示该场比赛的两个选手,两个选手可能比赛多场.
Output
第一行表示赢得最多的人最少会赢多少场
Sample Input
4 4
1 2
1 3
1 4
1 2
1 2
1 3
1 4
1 2
Sample Output
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]); }*/ }