ACM -二分图题目小结(更新中)

暂时只包括与最大匹配相关的问题。

求最大独立集,最小路径覆盖等等大多数题目都可以转化为求最大匹配用匈牙利算法解决。

1.最大匹配(边集)

此类问题最直接,直接用匈牙利算法即可。

HDU 2063  过山车

http://acm.hdu.edu.cn/showproblem.php?pid=2063

二分图最大匹配模版题。

ZOJ 1654 - Place the Robots

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1654

易想到求最大独立集但是时间复杂度太高,可以变成二分图最大匹配来做,重在建模。

2.最小路径覆盖(边集)

对于不存在孤立的点的图,|最小路径覆盖|+|最大匹配|=V(顶点数)

因此可以通过求最大匹配来做。

这个等式在DAG图中也成立,详见http://www.cnblogs.com/jackiesteed/articles/2043934.html。对于DAG图可以拆点来做。

HDU 1151 Air Raid

http://acm.hdu.edu.cn/showproblem.php?pid=1151

 1 #include<iostream>
2 #include<cstring>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstdlib>
6 #include<cstdio>
7 #include<vector>
8 #define MAXN 1005
9 using namespace std;
10 bool gl[MAXN][MAXN];
11 int link[MAXN];
12 int n;
13 bool vis[MAXN];
14
15 bool match(int x)
16 {
17 for(int i=1; i<=n; ++i)
18 if(gl[x][i]&&!vis[i])
19 {
20 vis[i]=true;
21 if(link[i]==-1||match(link[i]))
22 {
23 link[i]=x;
24 return true;
25 }
26 }
27 return false;
28 }
29 int main()
30 {
31 int T;
32 scanf("%d",&T);
33 while(T--)
34 { int m;
35 scanf("%d%d",&n,&m);
36 memset(gl,0,sizeof(gl));
37 for(int i=0;i<m;++i)
38 {
39 int x,y;
40 scanf("%d%d",&x,&y);
41 gl[x][y]=true;
42 }
43 int res=0;
44 memset(link,-1,sizeof(link));
45 for(int i=1; i<=n; ++i)
46 {
47 memset(vis,0,sizeof(vis));
48 if(match(i)) res++;
49 }
50 printf("%d\n",n-res);
51 }
52 return 0;
53 }

求DAG的最小路径覆盖。

3.最小顶点覆盖(点集)

在二分图中|最大匹配|=|最小顶点覆盖|,但是注意要解决的问题本身并不是最大匹配,理解了问题本身才能建模。

HDU 1054  Strategic Game

http://acm.hdu.edu.cn/showproblem.php?pid=1054

此题可以用树形DP来做也可以用求最小顶点覆盖,但是时间较慢。拆点,改成双向图,用邻接表。

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<vector>
#define MAXN 1505
using namespace std;
vector<int> gl[MAXN];
int link[MAXN];
int n;
bool vis[MAXN];
void init()
{
memset(link,-1,sizeof(link));
memset(vis,0,sizeof(vis));
}

bool match(int x)
{
for(int i=0; i<gl[x].size(); ++i)
{
int &u=gl[x][i];
if(!vis[u])
{
vis[u]=true;
if(link[u]==-1||match(link[u]))
{
link[u]=x;
return true;
}
}
}

return false;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(gl,0,sizeof(gl));
for(int i=0; i<n; ++i) gl[i].clear();
for(int i=0; i<n; ++i)
{
int now,t,cn;
scanf("%d:",&now);
scanf("(%d)",&cn);
while(cn--)
{
scanf("%d",&t);
gl[now].push_back(t);
gl[t].push_back(now);
}
}
init();
int res=0;
for(int i=0; i<n; ++i)
{
memset(vis,0,sizeof(vis));
if(match(i)) res++;
}
printf("%d\n",res/2);
}
return 0;
}

HDU 1150  Machine Schedule

http://acm.hdu.edu.cn/showproblem.php?pid=1150

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<vector>
#define MAXN 1005
using namespace std;
bool gl[MAXN][MAXN];
int link[MAXN];
int n,m;
bool vis[MAXN];

bool match(int x)
{
for(int i=1; i<=m; ++i)
if(gl[x][i]&&!vis[i])
{
vis[i]=true;
if(link[i]==-1||match(link[i]))
{
link[i]=x;
return true;
}
}
return false;
}
int main()
{
int t;
while(scanf("%d",&n)&&n)
{
scanf("%d%d",&m,&t);
memset(gl,0,sizeof(gl));
for(int i=0; i<t; ++i)
{
int x,y,z;
scanf("%d%d%d",&z,&x,&y);
gl[x][y]=true;
}
int res=0;
memset(link,-1,sizeof(link));
for(int i=1; i<=n; ++i)
{
memset(vis,0,sizeof(vis));
if(match(i)) res++;
}
printf("%d\n",res);
}
return 0;
}

4.最大独立集(点集)

|最大独立集|+|最小顶点覆盖|=V

求最大独立集是NP问题,但是在二分图中|最大匹配|=|最小顶点覆盖|,所以这个问题也有了高效的算法。

HDU 1045  Fire Net

http://acm.hdu.edu.cn/showproblem.php?pid=1045

这个可以暴力求最大独立集。

HDU 2768  Cat vs. Dog

http://acm.hdu.edu.cn/showproblem.php?pid=2768

根据矛盾之间建图,求最大独立集。

HDU 1068  Girls and Boys

http://acm.hdu.edu.cn/showproblem.php?pid=1068

题意很明显就是求二分图最大独立集。但是由于没说给的是男还是女,所以需要拆点,得到的最大匹配数要除以2,再套用公式得最大独立集。

 1 #include<iostream>
2 #include<cstring>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstdlib>
6 #include<cstdio>
7 #include<vector>
8 #define MAXN 1005
9 using namespace std;
10 bool gl[MAXN][MAXN];
11 int link[MAXN];
12 int n;
13 bool vis[MAXN];
14 void init()
15 {
16 memset(link,-1,sizeof(link));
17 memset(vis,0,sizeof(vis));
18 }
19
20 bool match(int x)
21 {
22 for(int i=0; i<n; ++i)
23 if(gl[x][i]&&!vis[i])
24 {
25 vis[i]=true;
26 if(link[i]==-1||match(link[i]))
27 {
28 link[i]=x;
29 return true;
30 }
31 }
32 return false;
33 }
34 int main()
35 {
36 while(scanf("%d",&n)!=EOF)
37 {
38 memset(gl,0,sizeof(gl));
39 for(int i=0; i<n; ++i)
40 {
41 int now,t,cn;
42 scanf("%d: ",&now);
43 scanf("(%d) ",&cn);
44 while(cn--)
45 {
46 scanf("%d",&t);
47 gl[now][t]=true;
48 }
49 }
50 init();
51 int res=0;
52 for(int i=0; i<n; ++i)
53 {
54 memset(vis,0,sizeof(vis));
55 if(match(i)) res++;
56 }
57 printf("%d\n",(n*2-res)/2);
58 }
59 return 0;
60 }

5.判断二分图

此类问题可以BFS或DFS解决,注意图可能不连通。

HDU 4751 Divide Groups

http://acm.hdu.edu.cn/showproblem.php?pid=4751

根据不互相认识这一关系连边,判断二分图。

ACM -二分图题目小结(更新中)

时间: 2024-08-10 02:11:41

ACM -二分图题目小结(更新中)的相关文章

我觉得有意思的JavaScript题目(01-05更新中)

对于以下js题目均来至于网络中.有的来至于文章之中,有的也许来至于问答题型中. 如果你有更好的问题解释,请留言交流! 1.相关问题描述:到底该怎么去理解闭包? 代码片段A: !function(){ var num=1; var exp={}; functionadd(num){ return num++; } exp.getAddNum=function(){ return add(num); } window.a=exp; }() console.log(a.getAddNum()); //

js坑爹笔试题目汇总(持续更新中)

把你的面试官问倒,你就是一个合格的面试者了,下面总结一些易错的js笔试题目,会持续更新中,欢迎关注 1,考察this var length = 10 function fn(){ alert(this.length) } var obj = { length: 5, method: function(fn) { fn() // ? arguments[0]() // ? } } obj.method(fn) 这里的坑主要是arguments,我们知道取对象属于除了点操作符还可以用中括号,这里fn

PTA|团体程序设计天梯赛-练习题目题解锦集(C/C++)(持续更新中……)

PTA|团体程序设计天梯赛-练习题目题解锦集(持续更新中) 实现语言:C/C++:      欢迎各位看官交流讨论.指导题解错误:或者分享更快的方法!! 题目链接:https://pintia.cn/problem-sets/994805046380707840/problems 目录 (点击对应题目即可进入相应题解--小声BB--) L1-001 Hello World (5 分) L1-002 打印沙漏 (20 分) L1-003 个位数统计 (15 分) L1-004 计算摄氏温度 (5

博弈论类题目小结——转载

出处http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 首先当然要献上一些非常好的学习资料: 基础博弈的小结:http://blog.csdn.net/acm_cxlove/article/details/7854530 经典翻硬币游戏小结:http://blog.csdn.net/acm_cxlove/article/details/7854534 经典的删边游戏小结:http://blog.csdn.net/acm

linux网络编程学习笔记之二 -----错误异常处理和各种碎碎(更新中)

errno 在unix系统中对大部分系统调用非正常返回时,通常返回值为-1,并设置全局变量errno(errno.h),如socket(), bind(), accept(), listen().erron存放一个正整数来保存上次出错的错误值. 对线程而言,每个线程都有专用的errno变量,不必考虑同步问题. strerror converts to English (Note: use strerror_r for thread safety) perror is simplified str

shell脚本练习题(更新中...)

练习题(这里贴的是自己写的代码, 网上给的题目代码我会附加在最下面) 1. 编写shell脚本,计算1-100的和: 1 #!/bin/bash 2 #caculate the sum of numbers from 1 to 100 3 4 sum=0 5 for i in `seq 1 100`; do 6 sum=$[$sum+$i] 7 done 8 echo $sum 2. 编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到

阿里笔试题(2015)持续更新中

第一次做阿里笔试题,除了ACM题之外从来没有做过校招网络题呀,完全是裸考,总体感觉吧,对于我来说,感觉时间不够用,不是题不会,感觉时间紧,大脑很混乱,总结这一次的笔试题 废话不多说,直接上题和答案 平均每个人逗留时间为20分钟,那么开场前20分钟一共来了400人,且有20个人逗留时间已经到,但他们不一定出去,注意是平均时间,所有博物馆最少应该容纳500人 双向循环列表,从任何一个元素开始可以遍历全部元素 先和后面的元素相连 s->next=p->next; p->next->pre

ACM 字符串 题目整理

AC自动机 UVa 11468  Substring AC自动机+概率DP. 注意要补全不存在的边. 为什么要补全不存在的边呢?补全以后可以直接找到状态的转移,即从所有子节点就可以实现所有状态转移. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cst

Android开发面试经——4.常见Android进阶笔试题(更新中...)

Android开发(29)  版权声明:本文为寻梦-finddreams原创文章,请关注:http://blog.csdn.net/finddreams 关注finddreams博客:http://blog.csdn.net/finddreams/article/details/44301359 上一篇文章我们已经了解了Android笔试的一些基础题目, [<Android开发面试经——2.常见Android基础笔试题> ] (http://blog.csdn.net/finddreams/a