当前位置: 代码迷 >> 综合 >> 二分图最小点覆盖 POJ1325 Machine Schedule POJ2226 Muddy Fields
  详细解决方案

二分图最小点覆盖 POJ1325 Machine Schedule POJ2226 Muddy Fields

热度:67   发布时间:2023-11-28 03:29:42.0

二分图最小点覆盖

给定一张二分图,求出一个最小的点集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;
}

  相关解决方案