二分图最小点覆盖
给定一张二分图,求出一个最小的点集S,使得图中任意一条边都有至少一个端点S,这个问题被称为二分图的最小点覆盖,简称最小覆盖
这种问题的模型特点是 每条边有两个端点,二者至少选择一个 这是2要素。
Konig定理
二分图最小点覆盖包含的点数等于二分图最大匹配包含的边数
上面这个定理的证明这里就不证了 网上可以搜到
这个证明很关键的一点让我们可以把这个最小覆盖问题的求解转化为对于最大匹配的求解
POJ1325 Machine Schedule
原题链接
题目大意
有AB两台机器 一共有N个任务 每台机器有M不同的模式 第i个任务可以在A机器上以a[i] ,在B机器上以b[i]进行。
每次转化模式 会重启 问你如何让重启次数最少
题目思路
让a的m种模式作为左部图 b的m种模式作为右部图 每个任务作为无向边链接
让重启次数最少 = 让机器使用的模式种类最少 = 二部图中的点最少=最小点覆盖问题=最大匹配问题
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=1e2+10;
int n,m,k;
int a[maxn],b[maxn];
struct node{int next,to,dis;
}e[maxn*maxn];
int cnt=0,head[maxn*10],vis[maxn],match[10*maxn];
void add(int u,int v,int d)
{e[++cnt].dis=d;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
}
bool dfs(int x)
{for(int i=head[x];i;i=e[i].next){int y=e[i].to;if(vis[y]==0){vis[y]=1;if(-1==match[y]||dfs(match[y])){match[y]=x;return 1;}}}return 0;
}
void init()
{memset(e,0,sizeof(e));memset(match,-1,sizeof(match));memset(head,0,sizeof(head));cnt=0;
}
int main()
{while(cin>>n){if(n==0)break;cin>>m>>k;init();for(int i=1;i<=k;i++){int x,c,b;cin>>x>>b>>c;//cout<<x<<" "<<a[x]<<" "<<b[x]<<endl;if (!c || !b) continue;add(b,c,1);//add(a[i],b[i],1);}int ans=0;for(int i=0;i<n;i++){memset(vis,0,sizeof(vis));if(dfs(i))ans++;}cout<<ans<<endl;}return 0;
}
POJ2226 Muddy Fields
题目链接
题目大意
n*m的格子有的格子脏 有的干净 你需要用1*x的板子覆盖这些脏地方 要求 板子长度不限 数量不限不能覆盖干净地方 但是可以重复覆盖脏地方
题目思路
每块(i,j)泥地要么被i行的一块横着的模板盖住 要么被j列的一块竖着的木板盖住 而这至少选择一个 这是题目的2要素
把一些横着的模板作为左部点 竖着的模板作为右部点 如果(i,j)是脏的那么让这块地上的横模板和竖模板链接 求出二分图最小覆盖,就是用最少的木板覆盖所有泥地
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=1e3+10;
int n,m;
char c[60][60];
int h[60][60],l[60][60];
struct node{int next,to,dis;
}e[maxn*maxn];
int cnt=0,head[maxn*10],vis[maxn],match[10*maxn];
void add(int u,int v,int d)
{e[++cnt].dis=d;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
}
bool dfs(int x)
{for(int i=head[x];i;i=e[i].next){int y=e[i].to;if(vis[y]==0){vis[y]=1;if(match[y]==-1||dfs(match[y])){match[y]=x;return 1;}}}return 0;
}
int main()
{cin>>n>>m;memset(match,-1,sizeof(match));for(int i=0;i<n;i++){scanf("%s",&c[i]);//printf("%s",c[i]+1);}int cnt1=0;for(int i=0;i<n;i++){ int flag=0;for(int j=0;j<m;j++){if(c[i][j]=='*'&&flag==0){flag=1;h[i][j]=++cnt1;}else if(flag==1){if(c[i][j]=='*'){h[i][j]=cnt1;}else {flag=0;}}}}int cnt2=0;for(int j=0;j<m;j++){ int flag=0;for(int i=0;i<n;i++){if(c[i][j]=='*'&&flag==0){flag=1;l[i][j]=++cnt2;}else if(flag==1){if(c[i][j]=='*'){l[i][j]=cnt2;}else {flag=0;}}}}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(c[i][j]=='.')continue;//cout<<h[i][j]<<endl;add(h[i][j],l[i][j],1);}}int ans=0;//cout<<cnt<<endl;for(int i=1;i<=cnt1;i++){memset(vis,0,sizeof(vis));if(dfs(i))ans++;}cout<<ans<<endl;return 0;
}