【最大流】BZOJ1305-[CQOI2009]dance跳舞
【题目大意】
一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?
【思路】
假设当前有a首舞曲。
把每个人拆成两个点,从“喜欢”到“不喜欢”连一条容量为k的边。从S往“男孩喜欢”连一条容量为a的边,从“女孩喜欢”往T连一条容量为a的边。
然后对于每对男孩女孩,如果不喜欢,则从“男孩不喜欢”到“女孩不喜欢”连一条容量为1的边,否则从“男孩喜欢”到“女孩喜欢”连一条容量为1的边。
为什么这个是正确的呢?这样相当于喜欢的人之间限制住了至多跳一首,而最多和k个不喜欢的人跳舞。画图感受一下就好了。
如果这a首舞曲都能用到,那么这个网络流应该是满流的。
所以二分答案。
注意很重要的两点:
①二分最后ub还要单独判断一下。
②不要忘了每次E的容量会被修改,所以暂存到rE每次重新回到原始状态。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define INF 0x7fffffff
#define S 0
#define T 4*n+1
using namespace std;
struct node
{
int to,pos,cap;
};
const int MAXN=+;
int n,k;
vector<node> E[MAXN*+];
vector<node> tmpE[MAXN*+];
int dis[MAXN*+]; void addedge(int u,int v,int w)
{
tmpE[u].push_back((node){v,tmpE[v].size(),w});
tmpE[v].push_back((node){u,tmpE[u].size()-,});
E[u].push_back((node){v,E[v].size(),w});
E[v].push_back((node){u,E[u].size()-,});
} bool bfs()
{
memset(dis,-,sizeof(dis));
queue<int> que;
while (!que.empty()) que.pop();
que.push(S);
dis[S]=;
while (!que.empty())
{
int head=que.front();que.pop();
if (head==T) return true; //首次抵达T即可返回,不需要整张图全部分层
for (int i=;i<E[head].size();i++)
{
node tmp=E[head][i];
if (dis[tmp.to]==- && tmp.cap)
{
dis[tmp.to]=dis[head]+;
que.push(tmp.to);
}
}
}
return false;
} int dfs(int s,int e,int f)
{
if (s==e) return f;
int ret=;
for (int i=;i<E[s].size();i++)
{
node &tmp=E[s][i];
if (dis[tmp.to]==dis[s]+ && tmp.cap)
{
int delta=dfs(tmp.to,e,min(f,tmp.cap));
if (delta>)
{
tmp.cap-=delta;
E[tmp.to][tmp.pos].cap+=delta;
f-=delta;
ret+=delta;
if (f==) return ret;
}
else dis[tmp.to]=-;
}
}
return ret;
} int dinic()
{
int flow=;
while (bfs())
{
int f=dfs(S,T,INF);
if (f) flow+=f;else break;
}
return flow;
} void init()
{
scanf("%d%d",&n,&k);
//0 源点
//1~n 男性喜欢
//n+1~2n 男性不喜欢
//2n+1~3n 女性不喜欢
//3n+1~4n 女性喜欢
//4n+1 汇点
for (int i=;i<=n;i++) addedge(i,i+n,k);
for (int i=*n+;i<=*n;i++) addedge(i,i+n,k);
for (int i=;i<=n;i++)
{
char str[MAXN];
scanf("%s",str+);
for (int j=;j<=n;j++)
{
if (str[j]=='Y') addedge(i,*n+j,);
else addedge(n+i,*n+j,);
}
}
for (int i=;i<=n;i++) addedge(S,i,);
for (int i=*n+;i<=*n;i++) addedge(i,T,);
} void solve()
{
int lb=,ub=n;
while (lb+<ub)
{
for (int i=S;i<=T;i++)
for (int j=;j<E[i].size();j++) E[i][j]=tmpE[i][j];
int mid=(lb+ub)>>;
for (int i=;i<n;i++) E[S][i].cap=mid;
for (int i=*n+;i<=*n;i++) E[i][E[i].size()-].cap=mid;
int d=dinic();
if (d==mid*n) lb=mid;else ub=mid;
}
for (int i=S;i<=T;i++)
for (int j=;j<E[i].size();j++) E[i][j]=tmpE[i][j];
for (int i=;i<n;i++) E[S][i].cap=ub;
for (int i=*n+;i<=*n;i++) E[i][E[i].size()-].cap=ub;
int d=dinic();
printf("%d",(d==ub*n)?ub:lb);
} int main()
{
init();
solve();
return ;
}
【最大流】BZOJ1305-[CQOI2009]dance跳舞的更多相关文章
- BZOJ1305 [CQOI2009]dance跳舞 【网络流】
1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 3714 Solved: 1572 [Submit][ ...
- bzoj1305: [CQOI2009]dance跳舞(二分答案+网络流)
1305: [CQOI2009]dance跳舞 题目:传送门 题解: 一眼网络流基础建模...然后就GG了 二分答案+拆点建边+最大流判断: 把男女生拆为男1,男2,女1,女2 1.男1和男2还有女1 ...
- bzoj千题计划130:bzoj1305: [CQOI2009]dance跳舞
http://www.lydsy.com/JudgeOnline/problem.php?id=1305 每个人拆为喜欢(yes)和不喜欢(no)两个点 二分答案 1.每两个人之间只能跳一次 喜欢则 ...
- 【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞
http://hzwer.com/1986.html #include<cstdio> #include<algorithm> #include<queue> #i ...
- Bzoj1305 [CQOI2009]dance跳舞
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 2925 Solved: 1221 Description 一次舞会有n个男孩和n个女孩.每首曲子开始时 ...
- 并不对劲的bzoj1305: [CQOI2009]dance跳舞
传送门-> 又是陈年老坑. 听上去不知道从何下[手]?那要是把题目换成“判断这些人能否条x支舞”呢? 这样就变成了一个网络流可以解决的问题,只要把每个人拆成喜欢和不喜欢两点,每个人两点总流量不超 ...
- BZOJ 1305: [CQOI2009]dance跳舞 二分+最大流
1305: [CQOI2009]dance跳舞 Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲 ...
- [CQOI2009]dance跳舞(最大流+二分)
[CQOI2009]dance跳舞 每个人拆成$2$个点,表示是否与喜欢的人跳舞 跳$m$首舞曲时,满足最大流为$n*m$ 二分$m$,跑最大流即可 #include<cstdio> #i ...
- BZOJ 1305: [CQOI2009]dance跳舞( 最大流 )
云神代码很短...0 ms过的...看了代码 , 大概是贪心... orz 我不会证 数据这么小乱搞就可以了吧... ←_← 这道题网络流还是可以写的... 既然限制了最多只能和 k 个不喜欢的人da ...
- AC日记——[CQOI2009]DANCE跳舞 洛谷 P3153
[CQOI2009]DANCE跳舞 思路: 二分+最大流: 代码: #include <cstdio> #include <cstring> #include <iost ...
随机推荐
- 探索ReactNative应用
本篇文章是我看AC2016腾讯前端技术交流大会后写的.写的不好,大家见谅啊. 一,什么是ReactNative? 简单来说就是可以用javascript来写APP了,而且性能还不错. 用JS写的话已经 ...
- DXEditingRow的错误原因
原因之一:例如commbox理由id这一列但是数据库表中没有的话就会报这个错误
- The content of element type "resultMap" must match "(constructor?,id*,result*,association*,collectio
The content of element type "resultMap" must match "(constructor?,id*,result*,associa ...
- C# 笔记——覆盖和重写
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...
- linux命令(34):less命令
1.命令格式: less [参数] 文件 2.命令功能: less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会 ...
- LeetCode212. Word Search II
https://leetcode.com/problems/word-search-ii/description/ Given a 2D board and a list of words from ...
- VS的使用
配置一个工程 问题描述: 要运行一个源码工程,工程中含有层级目录,.cpp与.h在多级目录中混合存储.并且该工程的运行依赖一些静态库(.lib)与动态库(.dll). 建立: 把.h拷贝至$(Proj ...
- css3之nth-child和nth-of-type的区别
之前一直开发的是兼容老版本的代码,所以很少用到有关c3里面的代码格式,今天就对于使用的c3选择器中nth-child和nth-of-type做一个区分.首先:1.nth-child(n):是选择父级元 ...
- Accord.NET入门
0.序 园子里介绍Accord.NET的文章不少,但是具体讲如何使用的反而不多,可能跟.NET在机器学习领域应用不多有关.诚然,如果做项目的话,可能用Python更好一些,但是如果把了解Accord. ...
- 事务时间如何去掉wasted time
事务时间如何去掉wasted time 事务时间 一个事务的时间是指持续时间,事务会完全记录下从事务开始到事务结束之间的时间差,那么事务的时间能真实地反映业务操作的时间吗?不能,就好像人用手按秒表 ...