HDU 3277Marriage Match III(二分+并查集+拆点+网络流之最大流)

2024-08-24 22:08

本文主要是介绍HDU 3277Marriage Match III(二分+并查集+拆点+网络流之最大流),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目地址:HDU 3277

这题跟这题的上一版建图方法差不多,只不过需要拆点。这个点拆的也很巧妙,既限制了流量,还只限制了一部分,以前一直以为拆点会全部限制,原来也可以用来分开限制,学习了。

建图方法为:建一源点与汇点,将女孩进行拆点,拆成i和i+n,将i与源点连边,权值为mid,将i与i+n连边,权值为k,再将男孩与汇点连边,权值为mid,这时可以配对的就将i与相应的男孩连边,权值为1,不能配对的就将i+n与对应的男孩连边,这样的话对原来可配对的不会限制流量,对不可以配对的限制了流量k。最后判断是否满流。

这次居然又卡在了并查集上。。。。= = !简直无语。。不过这次卡是卡在优化上,这次的数据量比较大,利用上次的方法会TLE,于是这次不能再采用上次的方法了,这次是先对每个父节点可配对的进行标记,然后直接一次遍历即可。上一次的是对每个集合内的分别进行配对标记。。对并查集的运用还是不灵活。。

代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int head[800], source, sink, nv, cnt;
int cur[800], d[800], num[800], pre[800], q[800], bin[800], _hash[300][300];
struct N
{int boy, girl;
}pari[1000000];
int find1(int x)
{return bin[x]==x?x:bin[x]=find1(bin[x]);
}
void merger(int x, int y)
{int f1=find1(x);int f2=find1(y);if(f2!=f1)bin[f2]=f1;
}
struct node
{int u, v, cap, next;
}edge[1000000];
void add(int u, int v, int cap)
{edge[cnt].v=v;edge[cnt].cap=cap;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].v=u;edge[cnt].cap=0;edge[cnt].next=head[v];head[v]=cnt++;
}
void bfs()
{memset(d,-1,sizeof(d));memset(num,0,sizeof(num));queue<int>q;q.push(sink);d[sink]=0;num[0]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(d[v]==-1){d[v]=d[u]+1;num[d[v]]++;q.push(v);}}}
}
int isap()
{memcpy(cur,head,sizeof(cur));bfs();int flow=0, u=pre[source]=source, i;while(d[source]<nv){if(u==sink){int f=INF, pos;for(i=source;i!=sink;i=edge[cur[i]].v){if(f>edge[cur[i]].cap){f=edge[cur[i]].cap;pos=i;}}for(i=source;i!=sink;i=edge[cur[i]].v){edge[cur[i]].cap-=f;edge[cur[i]^1].cap+=f;}flow+=f;u=pos;}for(i=cur[u];i!=-1;i=edge[i].next){if(d[edge[i].v]+1==d[u]&&edge[i].cap){break;}}if(i!=-1){cur[u]=i;pre[edge[i].v]=u;u=edge[i].v;}else{if(--num[d[u]]==0) break;int mind=nv;for(i=head[u];i!=-1;i=edge[i].next){if(mind>d[edge[i].v]&&edge[i].cap){mind=d[edge[i].v];cur[u]=i;}}d[u]=mind+1;num[d[u]]++;u=pre[u];}}return flow;
}
int main()
{int t, n, m, k, f, i, j, a, b;scanf("%d",&t);while(t--){scanf("%d%d%d%d",&n,&m,&k,&f);for(i=1;i<=m;i++){scanf("%d%d",&pari[i].girl,&pari[i].boy);}for(i=1;i<=n;i++){bin[i]=i;}while(f--){scanf("%d%d",&a,&b);merger(a,b);}int high=n, low=0, mid, ans, x;while(low<=high){mid=(low+high)/2;source=0;sink=3*n+1;nv=sink+1;memset(head,-1,sizeof(head));cnt=0;memset(_hash,0,sizeof(_hash));for(i=1;i<=n;i++){add(source,i,mid);add(i,i+n,k);add(2*n+i,sink,mid);}for(i=1;i<=m;i++){int a=pari[i].girl;int b=pari[i].boy;_hash[find1(a)][b]=1;}for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(_hash[find1(i)][j]){add(i,j+2*n,1);}else{add(i+n,j+2*n,1);}}}x=isap();if(x>=n*mid){ans=mid;low=mid+1;}else{high=mid-1;}}printf("%d\n",ans);}return 0;
}


这篇关于HDU 3277Marriage Match III(二分+并查集+拆点+网络流之最大流)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103737

相关文章

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ