题目大意:2种机器A,B,A有n个工作模式0~n-1,B有m个工作模式0~m-1。一开始都工作在0模式,现在有k个工作,对于工作i可以工作在机器A的x模式或者B的y模式,机器切换模式要耗费时间,所以希望尽量少的切换模式。求机器完成k个工作最少的切换次数。
题目分析:根据题意很容易建一个二分图。顶点分别为机器A和机器B的工作模式,每个工作一条边。要求的就是这张图的最小点覆盖。而二分图的最小点覆盖=最大边独立即最大匹配,因此可以转化成二分图匹配问题。
trick:可以工作在0模式的工作免建图。
详情请见代码:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 105;
const int M = 1005;
int head[N];
int cx[N],cy[N];
struct edge
{
int to,next;
}g[M];
bool flag[N];
int m,n;
void build(int s,int e,int num)
{
g[num].to = e;
g[num].next = head[s];
head[s] = num;
}
int path(int u)
{
int i;
for(i = head[u];i != -1;i = g[i].next)
{
if(flag[g[i].to] == false)
{
flag[g[i].to] = true;
if(cy[g[i].to] == -1 || path(cy[g[i].to]))
{
cy[g[i].to] = u;
cx[u] = g[i].to;
return 1;
}
}
}
return 0;
}
int maxmatch()
{
int i;
int ans = 0;
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
for(i = 1;i < n;i ++)
if(cx[i] == -1)
{
memset(flag,false,sizeof(flag));
ans += path(i);
}
return ans;
}
int main()
{
int i,k;
int a,b,c;
while(scanf("%d",&n),n)
{
scanf("%d%d",&m,&k);
memset(head,-1,sizeof(head));
for(i = 1;i <= k;i ++)
{
scanf("%d%d%d",&a,&b,&c);
if(b == 0 || c == 0)
continue;
build(b,c,i);
}
printf("%d\n",maxmatch());
}
return 0;
}
//128K 0MS