bzoj1305 [CQOI2009]dance跳舞(二分答案+最大流判是否满流)
2017-11-23 16:23
483 查看
二分答案,如何判断mid是否合法呢?我们建图,把每个点分成两个点。喜欢点称为a,不喜欢点称为b,男生x喜欢女生y,则建边xa->ya,边权为1,不喜欢则建边xb->yb,边权为1,最多只能k个不喜欢,所以建边xa->xb,边权为k,yb->ya,边权为k。然后源点向所有xa建边,边权为mid,所有ya向汇点建边,边权为mid。跑dinic求出最大流,看是否满流(即是否mid次所有人都分配成功了)。
#include <bits/stdc++.h> using namespace std; #define ll long long #define N 310 #define inf 0x3f3f3f3f inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int n,k,h ,num=1,lev ; char mp[51][51]; struct edge{ int to,next,val; }data[6000]; inline void add(int x,int y,int val){ data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val; data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=0; } inline bool bfs(){ queue<int>q;memset(lev,0,sizeof(lev)); q.push(0);lev[0]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(lev[y]||!data[i].val) continue; lev[y]=lev[x]+1;q.push(y); } }return lev[300]; } int dinic(int x,int low){ if(x==300) return low;int tmp=low; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(lev[y]!=lev[x]+1||!data[i].val) continue; int res=dinic(y,min(low,data[i].val)); if(!res) lev[y]=0;tmp-=res;data[i].val-=res;data[i^1].val+=res; if(!tmp) return low; }return low-tmp; } inline bool jud(int x){ num=1; for(int i=1;i<=n;++i) data[++num].val=x,data[++num].val=0; for(int i=1;i<=n;++i) data[++num].val=x,data[++num].val=0; for(int i=1;i<=n;++i) data[++num].val=k,data[++num].val=0,data[++num].val=k,data[++num].val=0; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) data[++num].val=1,data[++num].val=0; int res=0;while(bfs()) res+=dinic(0,inf); return res==n*x; } int main(){ // freopen("a.in","r",stdin); n=read();k=read(); for(int i=1;i<=n;++i) scanf("%s",mp[i]+1); for(int i=1;i<=n;++i) add(0,i,0),add(n+i,300,0); for(int i=1;i<=n;++i) add(i,i+100,k),add(n+i+100,n+i,k); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) mp[i][j]=='Y'?add(i,n+j,1):add(i+100,n+j+100,1); int l=1,r=n; while(l<=r){ int mid=l+r>>1; if(jud(mid)) l=mid+1; else r=mid-1; }printf("%d\n",l-1); return 0; }
相关文章推荐
- BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流
- 【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞
- BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流
- 【bzoj1305】[CQOI2009]dance跳舞 最大流+二分答案
- 【BZOJ1305】[CQOI2009]dance跳舞【最大流】【二分】
- bzoj 1305: [CQOI2009]dance跳舞(二分+最大流)
- bzoj1305 [CQOI2009]dance跳舞 最大流 二分
- [BZOJ1305][CQOI2009]跳舞(二分答案+最大流)
- BZOJ1305 [CQOI2009]dance跳舞 最大流+二分
- 【二分+最大流】BZOJ1305 [CQOI2009]dance跳舞
- BZOJ 1305: [CQOI2009]dance跳舞 二分+最大流
- 【二分+最大流Dinic】BZOJ1305(CQOI2009)[dance跳舞]题解
- [BZOJ1305][CQOI2009]dance跳舞(枚举二分+最大流)
- BZOJ 1305: [CQOI2009]dance跳舞 多重匹配,网络最大流
- 【BZOJ1305】dance跳舞(最大流,裂点,二分答案)
- 【bzoj1305】[CQOI2009]dance跳舞 最大流
- BZOJ 1305: [CQOI2009]dance跳舞 最大流
- [二分+网络流] bzoj1305: [CQOI2009]dance跳舞
- bzoj1189 [HNOI2007]紧急疏散evacuate(二分答案+bfs+最大流判是否满流)
- 【最大流】BZOJ1305-[CQOI2009]dance跳舞