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 二分图 最小点覆盖

}

}

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 这道二分图最小点覆盖问题。通过这个例子,我们可以更加深入地理解二分图和网络流算法,并且掌握如何将实际问题转化为数学模型进行求解。