http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=364
http://poj.org/problem?id=1325
题目大意:
给两台机器A和B,他们分别有n和m个工作模式,初始的时候都在Mode_0状态上,切换工作模式的时候必须重启机子。给你K个任务,第i个任务可以运行在A的mode_x上,B的mode_y上,求完成所有工作所需最少重启次数。
思路:
好吧,不会做。看了大神的思路:
对于任务(i,x,y),我们在A机mode_x与B机mode_y之间连一条边.这样,题目就变成了一个二分图,我们的目的是完成所有任务,即覆盖所有线段,题目要求选择最少的点,使得每个线段至少有一个端点被选中(这个任务就被完成了),这就是最小点覆盖模型,答案是这个二分图的最大匹配.
#include<cstdio> #include<cstring> const int MAXN=200+10; int head[MAXN],len,res[MAXN]; bool vis[MAXN]; struct edge { int to,next; }e[MAXN*MAXN]; void add(int from,int to) { e[len].to=to; e[len].next=head[from]; head[from]=len++; } bool find(int a) { for(int i=head[a];i!=-1;i=e[i].next) { int id=e[i].to; if(!vis[id]) { vis[id]=true; if(res[id]==0 || find(res[id])) { res[id]=a; return true; } } } return false; } int main() { int n,m,k; while(scanf("%d",&n),n) { scanf("%d%d",&m,&k); memset(head,-1,sizeof(head)); len=0; memset(res,0,sizeof(res)); for(int i=1;i<=k;i++) { int t,x,y; scanf("%d%d%d",&t,&x,&y); if( x != 0 && y != 0 ) // 初始态是0,默认完成。 add(x,y); } int ans=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(find(i)) ans++; } printf("%d\n",ans); } return 0; }