题目大意:两台机器A和B,机器A有0~n-1中模式,B有0~m-1种模式,开始时A和B都工作在0模式;
给定K 个作业,对于作业j ,给定的约束条件是(i,x,y);表示作业i既可以工作在A的x模式下,也可以工作在B的y模式下;
我们要做的就是改变机器的顺序,给每个机器分配合适的作业,是机器重启次数最少.
构造二分图:把A的n个模式和B的m 个模式看做两个集合,作为图的顶点,如果某个作业再两个模式下都可以完成,则构造该边;
二部图的点覆盖数=匹配数
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 100+3
int nx,ny,num; //A 和B 的模式数目,num为作业数目
int g[MAXN][MAXN]; //邻接矩阵构造二分图
int cx[MAXN],cy[MAXN]; //集合A和B zhong de 匹配情况
int mk[MAXN]; //记录访问状态
int path(int u) //DFS 寻找增广路
{
for(int v=1;v<=ny;v++)
{
if(g[u][v] && !mk[v])
{
mk[v]=1;
if(!cy[v] || path(cy[v]))//v没有匹配,或者从c[v]可以使增广路增1
{
cx[u]=v; //把v匹配给u
cy[v]=u; //把u匹配给v;
return 1;
}
}
}
return 0;
}
int max_match() //求二分图的最大匹配
{
int res=0;
memset(cx,0,sizeof(cx));
memset(cy,0,sizeof(cy));
for(int i=1;i<=nx;i++)
{
memset(mk,0,sizeof(mk));
res+=path(i);
}
return res;
}
int main()
{
int x,i,j;
while(scanf("%d",&nx),nx)
{
scanf("%d%d",&ny,&num);
memset(g,0,sizeof(g)); //将图初始化为0
for(int k=0;k<num;k++)
{
scanf("%d%d%d",&x,&i,&j);
g[i][j]=1; //构造二分图
}
printf("%d\n",max_match());
}
return 0;
}