HDU-2444 二分图的判别和最大匹配数。

2023-12-08 22:32

本文主要是介绍HDU-2444 二分图的判别和最大匹配数。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:

n个人,有m对关系,问你能否把他们分成两组,使得他们任意两两之间都不相互认识。如果不能输出“No”否则,问你,他们之间最最多认识的人。

分析:

题意很明了,一个时要我们判断他们之间能否构成 二分图,另外求二分图的最大匹配数。

关于判断二分图。一个最基本的方法就是染色法,意思是:把他们有关系的用两种不同颜色染色。通过邻接矩阵搜索,如果有一对有关系,并且颜色是相同的。那么就不是二分图了。

二分匹配有两种算法,一种是匈牙利算法和Hopcroft算法。其前面是每次寻找一条增广路,时间复杂度为(v*E),而后面的是在匈牙利算法进行了改进,每次不止一次增广一个非饱和顶点,时间复杂度为(E*V^0.5),稍比前面快点。

匈牙利算法(47ms)

#include<stdio.h>
#include<string.h>
#define N 250
int used[N],match[N],rec[N];
int map[N][N],n,m,flag;void DFS(int i,int color)
{for(int j=1;j<=n;j++){if(map[i][j]){if(rec[j]==0){rec[j]=-color;DFS(j,-color);}else if(rec[j]==color){flag=false;return ;}if(flag==false)return ;}}
}bool find(int i)
{for(int j=1;j<=n;j++){if(map[i][j]&&!used[j]){used[j]=1;if(!match[j]||find(match[j])){match[j]=i;return true;}}}return false;
}int main()
{int k,x,y;while(scanf("%d %d",&n,&m)!=EOF){memset(map,0,sizeof(map));memset(rec,0,sizeof(rec));flag=true;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);map[x][y]=map[y][x]=1;}DFS(1,1);if(!flag){puts("No");continue;}	 int ans=0;memset(match,0,sizeof(match));for(int i=1;i<=n;i++){memset(used,0,sizeof(used));if(find(i))ans++;}printf("%d\n",ans/2);}return 0;
}

Hopcroft 算法(47ms) 由于测试数据不多,时间相差不多。

#include<cstdio>
#include<queue>
#include<cstring>
#define INF 1<<29
using namespace std;
const int N=250;
int vis[N],dx[N],dy[N],Mx[N],My[N];
int g[N][N],rec[N];
int n,m,dis,flag;void check(int i,int color)
{for(int j=1;j<=n;j++){if(g[i][j]){if(!rec[j]){rec[j]=-color;check(j,-color);}else if(rec[j]==color){flag=false;return;}if(flag==false) return;}}
}bool searchp()
{queue<int>Q;dis=INF;memset(dx,-1,sizeof(dx));memset(dy,-1,sizeof(dy));for(int i=1;i<=n;i++)if(Mx[i]==-1){Q.push(i);    //多条增广。 dx[i]=0;}while(!Q.empty()){int u=Q.front();Q.pop();if(dx[u]>dis) break;for(int v=1;v<=n;v++)if(g[u][v]&&dy[v]==-1){dy[v]=dx[u]+1;if(My[v]==-1) dis=dy[v];else{dx[My[v]]=dy[v]+1;Q.push(My[v]);}}}return dis!=INF;
}bool DFS(int u)
{for(int v=1;v<=n;v++){if(!vis[v]&&g[u][v]&&dy[v]==dx[u]+1){vis[v]=1;if(My[v]!=-1&&dy[v]==dis) continue;if(My[v]==-1||DFS(My[v])){My[v]=u;Mx[u]=v;return true;}}}return false;
}int MaxMatch()
{int res=0;memset(Mx,-1,sizeof(Mx));memset(My,-1,sizeof(My));while(searchp()){memset(vis,0,sizeof(vis));	for(int i=1;i<=n;i++)if(Mx[i]==-1&&DFS(i)) res++;}return res;
}int main()
{int x,y;while(~scanf("%d %d",&n,&m)){memset(g,0,sizeof(g));memset(rec,0,sizeof(rec));flag=true;for(int j=0;j<m;j++){scanf("%d %d",&x,&y);g[x][y]=g[y][x]=1;}check(1,1);if(!flag){puts("No");continue;}printf("%d\n",MaxMatch()/2);	}return 0;
}/*
5 5
3 5
2 1
4 5
3 2
1 5
*/


这篇关于HDU-2444 二分图的判别和最大匹配数。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

如何提高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

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while