POJ - 1325 Machine Schedule 二分图 最小点覆盖
dep[MAXN];cap;edge[cnt].next = head[u];head[u] = cnt;sizeof(dep));edge[i].cap -= dflow;
在我们的日常生活中,机器调度问题是一个非常重要的问题。例如,在工厂中,需要将不同种类的机器按照一定的顺序进行安排,以便能够快速高效地完成生产任务。这个问题可以被转化为一个数学模型,并使用图论算法进行求解。本文将介绍 POJ – 1325 Machine Schedule 这道经典二分图最小点覆盖问题。
首先,我们来了解一下什么是二分图和最小点覆盖。
所谓二分图,就是指一个无向图可以被划分为两个互不相交的子集 U 和 V ,并且所有边都连接 U 中的某个顶点和 V 中的某个顶点。如果从左边子集到右边子集存在一条路径,则称该路径为增广路。
而最小点覆盖,则是指在一个无向图中选取尽可能少的节点(即“覆盖”),使得每条边都至少与其中一个节点相连。
现在回到 POJ – 1325 这道题目上来。题目描述如下:
有 n 台机器和 m 道工序,每台机器只能完成部分工序,并且每道工序只能由一台机器完成。给定各机器可完成的工序,求出完成所有工序需要的最少机器数。
这道题可以被转化为一个二分图问题。我们将左边子集 U 中的节点表示为每台机器,右边子集 V 中的节点表示为每道工序。如果一台机器能够完成某道工序,则在它们之间连一条边。
根据二分图理论,最小点覆盖数等于最大匹配数。因此,我们只需要使用匈牙利算法或者网络流算法来求解即可。
下面是使用网络流算法求解 POJ – 1325 的代码:
“`
#include
#include
#include
#include
using namespace std;
const int MAXN = 500 + 10;
const int INF = 0x7fffffff;
int n, m;
int s, t;
int cnt = 1, head[MAXN], cur[MAXN], dep[MAXN];
bool vis[MAXN];
struct Edge
{
int to, next, cap;
} edge[2 * MAXN * MAXN];
void addEdge(int u, int v, int w)
edge[++cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].cap = w;
head[u] = cnt;
edge[++cnt].to = u;
edge[cnt].next = head[v];
edge[cnt].cap = 0; // 将反向边容量设为0
head[v] = cnt;
}
bool bfs()
memset(dep, -1, sizeof(dep));
dep[s] = 0;
queue q;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(dep[v] == -1 && edge[i].cap > 0) // 如果可以走
{
dep[v] = dep[u] + 1;
q.push(v);
}
![POJ – 1325 Machine Schedule 二分图 最小点覆盖缩略图 POJ - 1325 Machine Schedule 二分图 最小点覆盖](https://www.72715.net/wp-content/uploads/2023/05/31ef7dc1b184fa33fda46624c5c1a06b.png)
}
}
return dep[t] != -1;
int dfs(int u, int flow)
if(u == t || flow == 0) return flow;
int used = 0;
for(int &i = cur[u]; i != -1 && used < flow; i = edge[i].next)
{
int v = edge[i].to;
if(dep[v] == dep[u] + 1 && edge[i].cap > 0)
{
int dflow = dfs(v, min(edge[i].cap, flow – used));
if(dflow > 0)
{
used += dflow;
edge[i].cap -= dflow;
edge[i ^ 1].cap += dflow;
}
}
}
return used;
int dinic()
int maxFlow = 0;
while(bfs())
{
memcpy(cur, head, sizeof(head));
maxFlow += dfs(s, INF);
}
return maxFlow;
void init() // 初始化
memset(head, -1 ,sizeof(head));
cnt=1;
void solve()
s=2*n+2,t=s+1;// 源点是2*n+2,汇点是s+4
for(int i=1;i<=n;i++)
{
addEdge(s,i,1);
addEdge(i+n,t,1);
for(int i=1;i<=m;i++)
int u,v;
scanf(“%d%d”,&u,&v);
addEdge(u,v+n,1);
printf(“%dn”,n-dinic());
int main()
while(~scanf(“%d%d”,&n,&m))
init();
solve();
return 0;
在上面的代码中,我们使用了 Dinic 算法来求解最大流。具体来说,我们将源点 s 连向每台机器,并将每道工序连接到汇点 t 上。对于每个能够完成某道工序的机器,我们在它们之间连一条边。
最后输出 n 减去最大流即可得到答案。
这里要注意一下反向边的容量应该为0。
本文介绍了如何使用网络流算法求解 POJ – 1325 Machine Schedule 这道二分图最小点覆盖问题。通过这个例子,我们可以更加深入地理解二分图和网络流算法,并且掌握如何将实际问题转化为数学模型进行求解。