bzoj1305: [CQOI2009]dance跳舞
2016-01-18 08:54
417 查看
Description
一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?Input
第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。Output
仅一个数,即舞曲数目的最大值。Sample Input
3 0YYY
YYY
YYY
Sample Output
3HINT
N<=50 K<=30题解:
将男生i拆为两个点i1,i2,将女生j也拆为j1,j2,如果i和j互相喜欢,则由i1到j1连一条容量为1的边,否则由i2到j2连一条容量为1的边
对于男生i,由i1向i2连一条容量为k的边,对于女生j,由j2向j1连一条容量为k的边
然后二分次数tim,由S向每个男生i1连容量为tim的边,由每个女生j1向T连容量为tim的边,然后如果最大流=tim*n,则这个次数可行
code:
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #define maxn 250 #define maxm 6000 #define inf 1061109567 using namespace std; char ch; bool ok; void read(int &x){ for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); if (ok) x=-x; } char g[55][55]; int n,k,l,r,m; struct flow{ int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm]; int dis[maxn],head,tail,list[maxn]; bool bo[maxn]; void init(){s=0,t=1,tot=1,memset(now,0,sizeof(now));} void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} void add(int a,int b,int c){put(a,b,c),put(b,a,0);} bool bfs(){ memset(bo,0,sizeof(bo)); head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1; while (head<tail){ int u=list[++head]; for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v; } return bo[t]; } int dfs(int u,int rest){ if (u==t) return rest; int ans=0; for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p]) if (val[p]&&dis[v]==dis[u]+1){ int d=dfs(v,min(rest,val[p])); val[p]-=d,val[p^1]+=d,ans+=d,rest-=d; } if (!ans) dis[u]=-1; return ans; } int dinic(){ int ans=0; while (bfs()) ans+=dfs(s,inf); return ans; } }f,tmp; bool check(int lim){ f=tmp; for (int i=1;i<=n;i++) f.add(f.s,i<<1,lim); for (int i=1;i<=n;i++) f.add((i+n)<<1,f.t,lim); return f.dinic()==lim*n; } int main(){ read(n),read(k),f.init(); for (int i=1;i<=n;i++) scanf("%s",g[i]+1); for (int i=1;i<=n;i++) f.add(i<<1,(i<<1)+1,k); for (int i=1;i<=n;i++) f.add(((i+n)<<1)+1,(i+n)<<1,k); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (g[i][j]=='Y') f.add(i<<1,(j+n)<<1,1); else f.add((i<<1)+1,((j+n)<<1)+1,1); for (tmp=f,l=0,r=n,m=((l+r)>>1)+1;l<r;m=((l+r)>>1)+1) if (check(m)) l=m; else r=m-1; printf("%d\n",l); return 0; }
相关文章推荐
- 支持移动端和PC端的轻量级轮播图插件&&hammer.js教程
- Java之学习笔记(4)---------------UML及面向对象
- freemarker常见语法大全
- linux 建议锁和强制锁
- Java之学习笔记(3)-----------学习Java的代码风格
- FreeMarker标签介绍
- centos 7 网络配置 ssd mysql nginx
- jQuery插件Validate实现自定义表单验证
- 控件
- Java之学习笔记(2)-----------Java的开发准备及环境配置
- linux2.6.30.4移植到TQ2440
- 2016年1月全国网络媒体技术联盟第七届年会的几个关键词
- paper 1:图像特征提取
- NSUserDefaults
- JAVA之学习笔记(1)-------------Java运行机制及JVM
- hdu 5600 N bulbs
- 错误代码: Could not load the "XXX.png" image referenced from a nib in the bundle with identifier "XXX"
- 百度touch.js API教程
- 1.自定义图书类
- C#除法精度