您的位置:首页 > 其它

poj 3041 二分图基础知识+匈牙利算法模版

2016-12-13 23:36 288 查看
二分图的定义:如果图的顶点可以分为2个互不相交的子集(A,B),则称这个图为二分图。

完全二分图:是指二分图两个集合中每个顶点与另外一个集合的所有顶点都有权值相连。

匹配:匹配是把两两存在公共边的的结点且未被匹配的结点相连。

增广路径:如果一条路径的首尾是非匹配点,路径中除此之外,其他的点均为匹配点,那么这条路径是一条增广路径。2个点也是一个增广路径。

每个增广路径都能变为比原来多一个匹配。

输入n,m  n为左边子集数,b有右边子集数,然后接下来m行表示m连接的点有哪些

样例输入:

4 6

1 1

1 1

5 1 3 4 5 6
4 4 5 6

样例输出:

3

代码:

#include <iostream>
#include <string.h>
using namespace std;

bool map[105][105],used[105];
int lin[105],n,m;

bool search(int a){
for(int i=1;i<=m;i++){
if(used[i]==0&&map[a][i]){
used[i]=1;
cout << a << "---->" << i << endl;
if(lin[i]==-1||search(pre[i])){
lin[i]=a;
cout << a  << "连上" << i << endl;
return 1;
}
}
}
return 0;
}

int main(){
freopen("in.txt","r",stdin);
int t1,t2,i,j,count=0;
cin >> n >> m;
memset(map,0,sizeof(map));
memset(lin,-1,sizeof(lin));
for(i=1;i<=n;i++){
cin >> t1;
for(j=1;j<=t1;j++){
cin >> t2;
map[i][t2]=1;
}
}
for(i=1;i<=n;i++){
memset(used,0,sizeof(used));
if(search(i))count++;
}
cout << "最大匹配图有" << count << endl;
}


最大二分图匹配复习,用vector来

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
vector<int>out[550];
int indegree[550];
int pre[550];
int walked[550];

int bfs(int x){
if(walked[x]==0){
walked[x]=1;
for(int i=0;i<out[x].size();i++){
if(pre[out[x][i]]==0||bfs(pre[out[x][i]])){
pre[out[x][i]]=x;
//cout << x << "pre---" << out[x][i] << endl;
return 1;
}
}
}
return 0;
}
int main(){
freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3;
int n,m;
scanf("%d%d",&n,&m);
memset(indegree,0,sizeof(indegree));
memset(out,0,sizeof(out));
memset(pre,0,sizeof(pre));
for(i=1;i<=n;i++){
cin >> f1;
for(j=1;j<=f1;j++){
cin >> f2;
out[i].push_back(f2);
}
}
for(i=1;i<=n;i++){
memset(walked,0,sizeof(walked));
bfs(i);
cout << i << endl;
}
for(i=1;i<=m;i++){
cout << "i=" <<i <<"      "<<pre[i] << endl;
}

return 0;
}

poj 3041

给一个网格,然后给出小型星的坐标,每次激光可以选择一个x或一个y整条线上的小行星全部消除,问最少需要几次激光。

由行星只能被x或y方向的激光消灭,且一个行星对应一个x与y,那么可以把所有x和y作为结点,又行星作为边,建立二分图

最小顶点覆盖是指:图中任意一条边都有一个顶点s属于V。

也就是求出最少的顶点数,这些顶点连接的边包括了整个图的全部边。

对于二分图 最小顶点覆盖=最大匹配

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

#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <stdlib.h>
using namespace std;
vector<int>qq[550];
int pre[550];
int walked[550];
int dfs(int x){
if(walked[x]==0){
walked[x]=1;
for(int i=0;i<qq[x].size();i++){
int u=qq[x][i];
if(pre[u]==-1||dfs(pre[u])){
pre[u]=x;
return 1;
}
}
}
return 0;
}
int main(){
//freopen("in.txt","r",stdin);
int t1,t2,t3,f1,f2,f3,i,j,k,l,n,m;
int k1,k2;
int g1,g2;
cin >> n>> m;
memset(pre,-1,sizeof(pre));
for(i=1;i<=m;i++){
cin >> t1>> t2;
qq[t1].push_back(t2);
//qq[t2].push_back(t1);
}
for(i=1;i<=n;i++){
memset(walked,0,sizeof(walked));
dfs(i);
}
t1=0;
for(i=1;i<=n;i++){
if(pre[i]!=-1)t1++;
}
cout << t1<< endl;
return 0;
}


dfs向下搜索发现pre被使用的时候,如果接着往下搜索,应该搜索pre[x]而不是x
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  最大匹配图