题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1305

题目大意:

一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?

思路:

二分答案,判断是否可行,每次二分答案时,用以下方式建图即可,判断是否满流,满流的话就是可行解。

 #include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#define Accepted 0
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快
const int INF = 1e9 + ;
const double eps = 1e-;
struct edge
{
int u, v, c, f;
edge(int u, int v, int c, int f):u(u), v(v), c(c), f(f){}
};
vector<edge>e;
vector<int>G[maxn];
int level[maxn];//BFS分层,表示每个点的层数
int iter[maxn];//当前弧优化 void init(int n)
{
for(int i = ; i <= n; i++)G[i].clear();
e.clear();
}
void addedge(int u, int v, int c)
{
e.push_back(edge(u, v, c, ));
e.push_back(edge(v, u, , ));
int m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
void BFS(int s)//预处理出level数组
//直接BFS到每个点
{
memset(level, -, sizeof(level));
queue<int>q;
level[s] = ;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int v = ; v < G[u].size(); v++)
{
edge& now = e[G[u][v]];
if(now.c > now.f && level[now.v] < )
{
level[now.v] = level[u] + ;
q.push(now.v);
}
}
}
}
int dfs(int u, int t, int f)//DFS寻找增广路
{
if(u == t)return f;//已经到达源点,返回流量f
for(int &v = iter[u]; v < G[u].size(); v++)
//这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
//在每次找增广路的时候,数组要清空
{
edge &now = e[G[u][v]];
if(now.c - now.f > && level[u] < level[now.v])
//now.c - now.f > 0表示这条路还未满
//level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
{
int d = dfs(now.v, t, min(f, now.c - now.f));
if(d > )
{
now.f += d;//正向边流量加d
e[G[u][v] ^ ].f -= d;
//反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
return d;
}
}
}
return ;
}
int Maxflow(int s, int t)
{
int flow = ;
for(;;)
{
BFS(s);
if(level[t] < )return flow;//残余网络中到达不了t,增广路不存在
memset(iter, , sizeof(iter));//清空当前弧数组
int f;//记录增广路的可增加的流量
while((f = dfs(s, t, INF)) > )
{
flow += f;
}
}
return flow;
}
int n, k;
char Map[][];
bool judge(int m)
{
int s = , t = * n + ;
init(t);
for(int i = ; i <= n; i++)
{
addedge(s, i, m);
addedge(i, n + i, INF);
addedge(i, * n + i, k);
addedge( * n + i, * n + i, INF);
addedge( * n + i, * n + i, k);
addedge( * n + i, t, m);
}
for(int i = ; i <= n; i++)
{
for(int j = ; j <= n; j++)
{
if(Map[i][j] == 'Y')//互相喜欢
addedge(n + i, * n + j, );
else addedge( * n + i, * n + j, );
}
}
return Maxflow(s, t) == n * m;
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = ; i <= n; i++)scanf("%s", Map[i] + );
int l = , r = n;
int ans = ;
while(l <= r)
{
int m = (l + r) / ;
if(judge(m))ans = m, l = m + ;
else r = m - ;
}
printf("%d\n", ans);
return Accepted;
}

BZOJ 1305 dance跳舞 二分+最大流的更多相关文章

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

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

  2. BZOJ 1305--[CQOI2009]dance跳舞(最大流)

    1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4150  Solved: 1792[Submit][St ...

  3. BZOJ 1305 dance跳舞(最大流+二分答案)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1305 解题思路:转自:https://blog.csdn.net/u012288458/ ...

  4. bzoj 1305 dance跳舞

    最大流. 首先二分答案,问题转化为x首舞曲是否可行. 考虑建图,对每个人建立三个点,分别表示全体,喜欢和不喜欢. 源点向每个男生全体点连一条容量为x的边. 每个男生整体点向喜欢点连一条容量为正无穷的边 ...

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

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

  6. BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

    题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连 ...

  7. BZOJ 1305: [CQOI2009]dance跳舞 网络最大流_二分答案_建模

    Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲.有一些男孩女孩相互喜欢,而其他相互不喜欢(不会 ...

  8. 1305. [CQOI2009]跳舞【最大流+二分】

    Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲.有一些男孩女孩相互喜欢,而其他相互不喜欢(不会 ...

  9. 【BZOJ1305】dance跳舞(最大流,裂点,二分答案)

    题意:一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲. 有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”). ...

随机推荐

  1. zTree中 checkbox 点击向文本框中赋值

    例子如下:第一个 文本框: <div class="content_wrap" style="height: 0;position: relative; " ...

  2. 【转】实现Sqlite datediff日期时间相减的方法

    对sqlite既恨又爱,在小项目里,用sqlite开发起来非常方便,效率足够用.美中不足的是sqlite精简了些功能及相关函数.如存储过程,datediff,不支持并发写入及远程访问(或许有些高手说这 ...

  3. loj#6235. 区间素数个数(min25筛)

    题意 题目链接 Sol min25筛的板子题,直接筛出\(g(N, \infty)\)即可 筛的时候有很多trick,比如只存\(\frac{N}{x}\)的值,第二维可以滚动数组滚动掉 #inclu ...

  4. css points

    <style type="text/css" rel="stylesheet">.a{ width:500px; height:400px;对放置图 ...

  5. php 截取字符串指定长度

    ---恢复内容开始--- 一.直接取整,舍弃小数,保留整数:intval(): intval(9.21); /*结果是9*/ intval(9.89); /*结果是9*/ intval(string) ...

  6. 前端AMD、CMD和commonJs-前端知识

    前端AMD和CMD是在模块化的基础上产生并且得到大幅度的引用的. AMD 即Asynchronous Module Definition(点击链接可以查看AMD面试题),中文名是异步模块定义的意思.它 ...

  7. 全功能开发团队(FSD)

  8. LK光流算法的三个假设

    在实际过程中采用 Lucas-Kanade 光流算法跟踪运动物体特征点的时候,一个很明显的特点是LK算法(包括其他光流算法)不能计算"大运动",加上金子塔的方法稍微好点. 这是什么 ...

  9. Android 通过URL获取网络资源

    1.先在AndroidManifest.xml中注册加入访问因特网服务的权限: <uses-permission android:name="android.permission.IN ...

  10. vxworks固件分析

    前言 vxworks 的固件分析流程 1.用binwalk查看固件基本信息并解压固件 2.获取固件相关信息, cpu架构,大小端 3.确定固件的加载地址 4.用IDA加载固件,并修复符号表 5. 分析 ...