POJ 1325 Machine Schedule
题目链接:POJ 1325
题意:
机器A有n个模式,机器B有m个模式。给k个作业,k个三个组(i,x,y)表示作业i可以由机器A的x模式或者机器B的y模式去做。
机器的模式切换是要重启,求机器最少的重启次数。
分析:
对于某个作业可以在A的模式i或者B的模式j完成,则Ai与Bj连接一条边。问题转化二分图的最小点覆盖数(利用最小点覆盖数=最大匹配数求出结果),需要注意的是A、B开始时都是在模式0.
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=200;
int n,m,k;
// BFS
const int maxn=512;
int g[maxn][maxn];
int L,R;
int x[maxn],y[maxn];
int Q[maxn]; //模拟队列
int pre[maxn];
int MaxMatch()
{
int res=0,temp;
memset(x,-1,sizeof(x));
memset(y,-1,sizeof(y));
for(int i=1;i<=L;i++)
{
if(x[i]==-1)
{
int cur=0,tail=0;
for(int j=1;j<=R;j++)
{
if(g[i][j])
pre[j]=-1,Q[tail++]=j;
else
pre[j]=-2;
}
//BFS
while(cur<tail)
{
temp=Q[cur];
if(y[temp]==-1)
break;
cur++;
for(int j=1;j<=R;j++)
{
if(pre[j]==-2&&g[y[temp]][j])
{
pre[j]=temp;
Q[tail++]=j;
}
}
}
//end of BFS
if(cur==tail) //没有找到交错轨
continue;
while(pre[temp]>-1) //更改交错轨上匹配状态
{
x[ y[pre[temp]] ]=temp;
y[temp]=y[pre[temp]];
temp=pre[temp];
}
y[temp]=i;x[i]=temp;
res++;
}
}
return res;
}
int main()
{
// freopen("in.txt","r",stdin);
int num,u,v;
while(scanf("%d",&n)!=EOF&&n)
{
scanf("%d %d",&m,&k);
L=n;R=m;
memset(g,0,sizeof(g));
for(int i=0;i<k;i++)
{
scanf("%d %d %d",&num,&u,&v);
g[u][v]=1;
}
printf("%d\n",MaxMatch());
}
return 0;
}