题目大意:
有两台机器A和B以及K个需要运行的任务。A机器有N种不同的模式,B机器有M种不同的模式,而每个任务都恰好在一台机器上运行。
如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi。
每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
题解:
把机器A的N种模式作为二分图的左部,机器B的M种模式作为二分图的右部,如果某个任务可以使用机器A的模式xi也可以使用机器B的模式yi完成,则连接xi,yi。
由于要使得机器重启的次数最少而又要完成所有的任务,题目转化为从这N+M个点中取出最少数量的点覆盖所有的边。
又根据二分图的性质:最小点覆盖=最大匹配数,可以使用匈牙利算法求出答案
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#define pau putchar(' ')
#define ent putchar('\n')
#define mse(a,b) memset(a,b,sizeof(a))
#define ren(x) for(ted*e=fch[x];e;e=e->nxt)
#define rep(i,s,t) for(int i=s,__=t;i<=__;i++)
#define dwn(i,s,t) for(int i=s,__=t;i>=__;i--)
using namespace std;
const int maxn=+,maxm=+;
int lnk[maxn];bool vis[maxn];
struct ted{int x,y;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj;
void add(int x,int y){*ms=(ted){x,y,fch[x]};fch[x]=ms++;return;}int n,m,k;
bool match(int x){
ren(x){int v=e->y;if(!vis[v]){vis[v]=true;
if(!lnk[v]||match(lnk[v])){lnk[v]=x;return true;}
}
}return false;
}
int hungary(){
mse(lnk,false);int ans=;rep(i,,n){mse(vis,false);if(match(i))ans++;}return ans;
}
inline int read(){
int x=;bool sig=true;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=false;
for(;isdigit(ch);ch=getchar())x=*x+ch-'';return sig?x:-x;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=;static int buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
int main(){
while(true){
n=read();if(!n)break;
mse(fch,NULL);ms=adj;
m=read();k=read();int x,y;
rep(i,,k){
read();x=read();y=read();if(x&&y)add(x,y);
}write(hungary());ent;
}
return ;
}