题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081

推荐博客:https://www.cnblogs.com/liuxin13/p/4728131.html

这个题目没什么思路,完全不知道怎么写,后来看了题解,说是网络流+二分+并查集,然后更加懵了。

然后就z继续看了详细解答,才知道怎么去写。

emmm...这个题目他是让你求不同男孩女孩全部都成功配对最多会有多少轮,每一轮的女孩配对的男生都不一样。

还有一个让题目复杂一点的就是女孩子有朋友,在一个女孩圈里,她朋友没吵过架的男生在下一轮里可以成为她的男朋友。

先不考虑女孩子有女孩圈里,也不求最多有多少轮,就是男生女生要全部成功配对,那就是一个网络流的裸题。

但是呢,现在要求最多有多少轮(不考虑女孩圈),那其实也很难想到二分。。。

不过有人提示你用二分了,这个就觉得二分可以做,而且感觉也特别对,那就这样写吧,至于解释就是一般求最值都要想到用二分,

而且这个还是可以找到单调性,这个单调性就是如果最大流==n*x(x是被二分枚举的答案)那就说明这个可以是答案,当然也可以更大一点,所以就更新这个l=mid+1

不然就是这个mid大了,所以这个r就更新为mid-1。

最后就是考虑有女孩圈了,既然有女孩圈,是一个圈,那就容易想到并查集,所以这个题目的第三个算法就是并查集,

但是这个并查集怎么用,我开始也不知道,后来看了一点点别人写的代码才理解的,这个就是把一个把一个圈子的女孩的所有男朋友都连到根节点上去。

这个样子,以后每一个女孩找男朋友都可以通过根节点去连线(建图)

大致思路就是这个样子的,接下来敲代码了。

非常郁闷,又找了一个晚上的bug,唉,好伤心,好想哭。。。。

最后还是刷牙的时候感觉自己的问题,我这么写很可能会同一边输入很多次,这个需要判断一下,哭了。。。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+; 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];//当前弧优化
int m;
void init()
{
for (int i = ; i <= maxn; 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, , ));
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 f[maxn], boy[maxn], girl[maxn];
vector<int>love[maxn]; int findx(int x)
{
return f[x] == x ? x : f[x] = findx(f[x]);
} void unite(int x,int y)
{
x = findx(x);
y = findx(y);
if (x == y) return;
f[x] = y;
}
int n;
bool vis[][];
void buildgrath(int flow,int s,int t)
{
init();
memset(vis, , sizeof(vis));
for(int i=;i<=n;i++)
{
if(!vis[s][i]) addedge(s, i, flow);
if(!vis[i+n][t]) addedge(i + n, t, flow); int u = findx(i);
int len = love[u].size(); for(int j=;j<len;j++)
{
if (vis[i][love[u][j]]) continue;
addedge(i, love[u][j], );
vis[i][love[u][j]] = ;
}
}
} int main()
{
int w;
scanf("%d", &w);
while(w--)
{
int m, fx;
scanf("%d%d%d", &n, &m, &fx);
for (int i = ; i <= *n+; i++)
{
f[i] = i;
love[i].clear();
}
for(int i=;i<=m;i++)
{
scanf("%d%d", &girl[i], &boy[i]);
}
for(int i=;i<=fx;i++)
{
int x, y;
scanf("%d%d", &x, &y);
unite(x, y);
}
int s = , t = n + n + ;
int l = , r = n;
for(int i=;i<=m;i++)
{
int u = findx(girl[i]);
love[u].push_back(boy[i] + n);
}
int ans = ;
while(l<=r)
{
int mid = (l + r) >> ;
buildgrath(mid, s, t);
int ex = Maxflow(s, t);
if(ex==n*mid)
{
l = mid + ;
ans = mid;
}
else r = mid - ;
}
printf("%d\n", ans);
}
return ;
}

N - Marriage Match II 网络流的更多相关文章

  1. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  2. HDU 3081 Marriage Match II 二分 + 网络流

    Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...

  3. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

  4. HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. hdu3081 Marriage Match II(最大流)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Marriage Match II Time Limit: 2000/1000 M ...

  6. HDU 3081 Marriage Match II(二分法+最大流量)

    HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...

  7. Marriage Match II(二分+并查集+最大流,好题)

    Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...

  8. HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    ...

  9. 【HDU3081】Marriage Match II (二分+最大流)

    Description Presumably, you all have known the question of stable marriage match. A girl will choose ...

随机推荐

  1. AJ学IOS 之微博项目实战(11)发送微博自定义TextView实现带占位文字

    AJ分享,必须精品 一:效果 二:代码: 由于系统自带的UITextField:和UITextView:不能满足我们的需求,所以我们需要自己设计一个. UITextField: 1.文字永远是一行,不 ...

  2. 前端学习笔记 --ES6新特性

    前言 这篇博客是我在b站进行学习es6课程时的笔记总结与补充. 此处贴出up主的教程视频地址:深入解读ES6系列(全18讲) 1.ES6学习之路 1.1 ES6新特性 1. 变量 2. 函数 3. 数 ...

  3. python编程语言是什么?它能做什么?

    Python是一种全栈的开发语言,你如果能学好Python,前端,后端,测试,大数据分析,爬虫等这些工作你都能胜任. 当下Python有多火我不再赘述,,Python有哪些作用呢? 就目前Python ...

  4. OpenAL试水

    参考了https://wysaid.org/976.html. 这个博客给了一个EGE+OpenAL的demo和源代码.一开始没注意,博主也没有给EGE相关信息.会找不到EGE相关头文件,建议如果要二 ...

  5. win10下cuda安装以及利用anaconda安装pytorch-gpu过程

    安装环境:win10+2070super 1.Cuda的下载安装及配置 (1)测试本机独立显卡是否支持CUDA的安装,点击此处查询显卡是否在列表中. (2)查看自己是否能右键找到NVIDA控制面板,如 ...

  6. 01、WireShark——ARP 协议包分析

     1. 什么是ARP ARP(Address Resolution Protocol)协议,即地址解析协议.该协议的功能就是将 IP 地 址解析成 MAC 地址. ARP(Address Resolu ...

  7. Chrome插件安利!可以一键导出微信读书笔记|支持Markdown等三种格式

    众所周知,微信读书App 是一款非常优秀的阅读类App ,周围也有不少人在用.虽然工作比较忙.但是也没少在上面看书做笔记. 美中不足的是,目前微信读书虽然支持笔记导出,但是提供的是将笔记复制到剪切板, ...

  8. ubuntu(Linux)下,查看CPU性能集合

    CPU: 详细:cat /proc/cpuinfo型号:grep "model name" /proc/cpuinfo |awk -F ':' '{print $NF}'数量:ls ...

  9. 2019-2020-1 20199303《Linux内核原理与分析》第七周作业

    进程的描述 1.进程概念 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位.进程由程序段.数据段.PCB组成 2.PCB中的信息 ①进程标识符 ②处理机状态 ③进程调度信息 ④进程控制 ...

  10. 十七, Oracle索引约束

    管理索引-原理介绍 索引是用于加速数据存取的数据对象.合理的使用索引可以大大降低i/o次数,从而提高数据访问性能. 单列索引 适当的索引对于大型数据库的性能有不错的提升, 但在创建索引时要小心.选择字 ...