题目大意是有A类机器和B类机器。某个产品生产可以用A类中的某一个或B类中的某一个。如果要使用某个机器(除编号为0的机器外),那么需要一个单位的开机时间,问你最少的开机时间。
对于每一个可以生产同一个产品的机器A和机器B连一条边(每条边代表一个产品)。那么我们要做的就是找到最小的点,使得这些点能覆盖所有的边(这些点能生产所有的的产品)。也就是求二分图的最小点覆盖。
因为用机器0是不需要开机时间的,所以那些可以用机器0完成的产品就不需要再建边了。
#include <iostream>
#include<cstring>
#include<stdio.h>
#define maxn 110
/**
匈牙利算法 O(VE)
假设从二分图左边开始找增广路
*/
using namespace std;
int n,m,k;
typedef struct edge
{
int to,next;
} Edge;
Edge e[1010];
int head[maxn];//邻接表存边,只需维护左边节点的邻接表
int vis[maxn];//右边点访问标记
int mat[maxn];//右边点匹配的左边点
int match;//匹配数
bool crosspath(int k)
{
for(int i = head[k]; i != -1; i = e[i].next)
{
int j = e[i].to;
if(!vis[j])
{
vis[j] = 1;
if(!mat[j] || crosspath(mat[j]))//右边点未匹配
{
mat[j] = k;
return true;
}
}
}
return false;
}
void hungary()
{
for(int i = 0; i <= n; i++)
{
memset(vis,0,sizeof vis);
if(crosspath(i))
{
match++;
}
}
}
int main()
{
while(scanf("%d",&n),n)
{
scanf("%d %d",&m,&k);
memset(head,-1,sizeof head);
memset(mat,0,sizeof mat);
for(int i = 0; i < k; i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
if(b&&c)//如果能用机器0生产就不用建边
{
e[i].to = c;
e[i].next = head[b];
head[b] = i;
}
}
match = 0;
hungary();
printf("%d\n",match);
}
return 0;
}