0
点赞
收藏
分享

微信扫一扫

POJ1325 Machine Schedule【二分图最小点覆盖】


题目链接:

​​http://poj.org/problem?id=1325​​


题目大意:

有两台机器A和B,机器A有N种不同的模式,编号为0~N-1。机器B有M种不同的模式,编号为0~M-1。

在一开始的时候,机器A和B都处于0模式。现在需要用两台机器来处理K项任务,任务编号为0~K-1。每

一项任务都可以在A或B的指定状态下完成。例如任务1可以在机器A的2模式下完成,也可以在机器B的4

模式下完成。对于第i想任务用(i,x,y)来表示第i项任务可以在机器A的x模式下或机器B的y模式下完成。

为了完成所有任务,不得一次次地切换机器的工作模式。而切换机器的工作模式只能通过重启机器来完

成。那么问题来了:最少需要重启多少次机器,能够完成这K项任务。


思路:

建立一个二分图,一边为机器A,另一边为机器B。一项任务既能在机器A的x模式或是机器B的y模式下完

成,则在二分图中建立一条边(x,y)。求最少的机器切换次数,就是求是否存在一个最小规模的点集,使

得所有的边都至少和这个点集中的一个点相关联,也就是求二分图最小点集覆盖。而二分图最小点覆盖等

于二分图最大匹配,直接用匈牙利算法就可以求出了。


AC代码:


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

const int MAXN = 110;

bool Map[MAXN][MAXN],Mask[MAXN];

int NX,NY;
int cx[MAXN],cy[MAXN];

int FindPath(int u)
{
for(int i = 0; i < NY; ++i)
{
if(Map[u][i] && !Mask[i])
{
Mask[i] = 1;
if(cy[i] == -1 || FindPath(cy[i]))
{
cy[i] = u;
cx[u] = i;
return 1;
}
}
}
return 0;
}

int MaxMatch()
{
for(int i = 0; i < NX; ++i)
cx[i] = -1;
for(int i = 0; i < NY; ++i)
cy[i] = -1;

int res = 0;
for(int i = 0; i < NX; ++i)
{
if(cx[i] == -1)
{
for(int j = 0; j < NY; ++j)
Mask[j] = 0;
res += FindPath(i);
}
}
return res;
}

int main()
{
int N,M,K,a,u,v;
while(~scanf("%d",&N) && N)
{
memset(Map,0,sizeof(Map));
scanf("%d%d",&M,&K);
NX = N,NY = M;
for(int i = 1; i <= K; ++i)
{
scanf("%d%d%d",&a,&u,&v);
if(u*v != 0)
Map[u][v] = 1;
}
printf("%d\n",MaxMatch());
}

return 0;
}



举报

相关推荐

0 条评论