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
代码:
最大二分图匹配复习,用vector来
poj 3041
给一个网格,然后给出小型星的坐标,每次激光可以选择一个x或一个y整条线上的小行星全部消除,问最少需要几次激光。
由行星只能被x或y方向的激光消灭,且一个行星对应一个x与y,那么可以把所有x和y作为结点,又行星作为边,建立二分图
最小顶点覆盖是指:图中任意一条边都有一个顶点s属于V。
也就是求出最少的顶点数,这些顶点连接的边包括了整个图的全部边。
对于二分图 最小顶点覆盖=最大匹配
最小顶点覆盖+最大独立集=V;
dfs向下搜索发现pre被使用的时候,如果接着往下搜索,应该搜索pre[x]而不是x
完全二分图:是指二分图两个集合中每个顶点与另外一个集合的所有顶点都有权值相连。
匹配:匹配是把两两存在公共边的的结点且未被匹配的结点相连。
增广路径:如果一条路径的首尾是非匹配点,路径中除此之外,其他的点均为匹配点,那么这条路径是一条增广路径。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
相关文章推荐
- poj 3041 二分匹配 基础题(整理版:基础知识)匈牙利算法
- 二分图最大匹配匈牙利算法(poj)3041(模板)
- 【二分图|最大匹配】POJ-3041 Asteroids(匈牙利算法dfs、bfs版)
- 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids
- POJ 3041 Asteroids 匈牙利算法 二分图最大匹配
- poj 3041 Asteroids【二分图】【匈牙利算法】
- 【POJ 3041 】Asteroids (匈牙利算法最小点覆盖&二分图)
- poj3041——Asteroids(二分图,匈牙利算法)
- poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)
- POJ-3041 匈牙利算法 二分图最大匹配
- poj 3041 Asteroids (匈牙利算法---二分图最大匹配)
- (模板题)poj 3041 Asteroids(二分图的最大匹配匈牙利算法)
- poj_3041 匈牙利算法
- POJ 3041 Asteroids(匈牙利算法—最小点覆盖)
- (POJ 3041)Asteroids 二部图最大匹配 匈牙利算法
- POJ 3041 Asteroids 【匈牙利算法最小点覆盖】
- POJ 3041 Asteroids (匈牙利算法)
- POJ 1325 Machine Schedule (二分图最小点集覆盖 匈牙利算法)
- poj 3041 Asteroids 匈牙利算法
- poj 2446 二分图最大匹配 匈牙利算法