题目请戳这里
题目大意: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