【题目大意】

一次舞会有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跳舞的更多相关文章

  1. BZOJ1305 [CQOI2009]dance跳舞 【网络流】

    1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 3714  Solved: 1572 [Submit][ ...

  2. bzoj1305: [CQOI2009]dance跳舞(二分答案+网络流)

    1305: [CQOI2009]dance跳舞 题目:传送门 题解: 一眼网络流基础建模...然后就GG了 二分答案+拆点建边+最大流判断: 把男女生拆为男1,男2,女1,女2 1.男1和男2还有女1 ...

  3. bzoj千题计划130:bzoj1305: [CQOI2009]dance跳舞

    http://www.lydsy.com/JudgeOnline/problem.php?id=1305 每个人拆为喜欢(yes)和不喜欢(no)两个点 二分答案 1.每两个人之间只能跳一次 喜欢则 ...

  4. 【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞

    http://hzwer.com/1986.html #include<cstdio> #include<algorithm> #include<queue> #i ...

  5. Bzoj1305 [CQOI2009]dance跳舞

    Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 2925  Solved: 1221 Description 一次舞会有n个男孩和n个女孩.每首曲子开始时 ...

  6. 并不对劲的bzoj1305: [CQOI2009]dance跳舞

    传送门-> 又是陈年老坑. 听上去不知道从何下[手]?那要是把题目换成“判断这些人能否条x支舞”呢? 这样就变成了一个网络流可以解决的问题,只要把每个人拆成喜欢和不喜欢两点,每个人两点总流量不超 ...

  7. BZOJ 1305: [CQOI2009]dance跳舞 二分+最大流

    1305: [CQOI2009]dance跳舞 Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲 ...

  8. [CQOI2009]dance跳舞(最大流+二分)

    [CQOI2009]dance跳舞 每个人拆成$2$个点,表示是否与喜欢的人跳舞 跳$m$首舞曲时,满足最大流为$n*m$ 二分$m$,跑最大流即可 #include<cstdio> #i ...

  9. BZOJ 1305: [CQOI2009]dance跳舞( 最大流 )

    云神代码很短...0 ms过的...看了代码 , 大概是贪心... orz 我不会证 数据这么小乱搞就可以了吧... ←_← 这道题网络流还是可以写的... 既然限制了最多只能和 k 个不喜欢的人da ...

  10. AC日记——[CQOI2009]DANCE跳舞 洛谷 P3153

    [CQOI2009]DANCE跳舞 思路: 二分+最大流: 代码: #include <cstdio> #include <cstring> #include <iost ...

随机推荐

  1. vue 点击选中改变样式

    data里isActive:-1,method里 checkedItem(index){ this.isActive=index;},页面里 <div v-for="(item,ind ...

  2. CSS 竖线 点 时间节点

    效果如图 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  3. css优先级机制

    所谓CSS优先级,即是指CSS样式在浏览器中被解析的先后顺序.   1.important >(内联样式)Inline style  >(内部样式)Internal style sheet ...

  4. Python 用ctypes观察Python对象的内存结构 -- (转)

    !!!强烈推荐的好文章!!! 对象的两个基本属性 Python所有对象结构体中的头两个字段都是相同的: refcnt:对象的引用次数,若引用次数为0则表示此对象可以被垃圾回收了. typeid:指向描 ...

  5. 动态替换Linux核心函数的原理和实现

    转载:https://www.ibm.com/developerworks/cn/linux/l-knldebug/ 动态替换Linux核心函数的原理和实现 在调试Linux核心模块时,有时需要能够实 ...

  6. linux irq 自动探测

    前言 编写驱动的时候,经常会用到中断,这时候我们在驱动初始化时就得申请中断,那么问题来了,中断号是多少呢?以前的中断号在板级相关的头文件里面已经静态定义好了,bsp的代码在内核启动过程也会根据那个帮我 ...

  7. python实战===代码

    #!/usr/bin/env python # encoding:utf-8 import requests import json from conf import STORE_DICT_LIST ...

  8. 基于 Arduino 开发板,这款插座是可编程且开源的

    基于 Arduino 开发板,这款插座是可编程且开源的 https://www.oschina.net/news/74861/open-source-socket https://github.com ...

  9. IntelliJ IDEA 启动方法

    IntelliJ IDEA cd idea-IU-145.1617.8/bin && ./idea.sh

  10. HDU-2819

    Swap Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...