poj 1325 Machine Schedule

/*

题意: 有两台机器A和B,分别有n种和m种不同的模式,
有k个工作,每个工作都可以在那两个机器的某种特定的模式下处理,
如job[0]既可以在A机器的3号模式下处理,也可以在B机器的4号模式下处理,
初始时两台机器都在0号模式下工作,机器的工作模式改变只能通过重启来改变,
通过改变工作的顺序和分配每个工作给合适的机器可以减少重启机器的次数,求重启机器的最少次数

思路: 令X,Y分别是机器A和B的工作模式集合,工作在A和B机器上的工作模式分别为X[a]和Y[b],让X[a]与Y[b]相连,
这样我们就可以X和Y作为两个顶点集合来建立二分图,重启机器的次数就是覆盖所有的边的顶点数。
所以问题就转化成在X和Y中用最少的顶点数来覆盖所有的边,也就是求二分图的最小点覆盖数
根据König定理可知二分图的最小点覆盖数等于最大匹配数
注意到机器A和B开始时都在模式0下工作,所以需要在0号模式下处理的工作都不必再重启机器
可以这么解决:1)在进行搜索和匹配的过程中,忽略掉0,即从顶点1,而不是从0开始
或者2)在建立二分图时,只有在a与b都不为0时才让a与b相连

*/

#include<iostream> // 求二分图的最小点覆盖数,相当于最大匹配数
#include<cstring>
using namespace std;
int edge[110][110],vis[110],link[110];
int n,m; // V1子集下标范围[1,n],V2子集下标范围[1,m]
int find(int a)
{
for(int i=2;i<=m;++i) // 忽略掉模式0
{
if( edge[a][i] && !vis[i] )
{
vis[i]=1;
if( link[i]==0 || find(link[i]) )
{
link[i]=a;
return 1;
}
}
}
return 0;
}
int main()
{
int k,p,t1,t2;
while(scanf("%d",&n),n)
{
memset(edge,0,sizeof(edge));
memset(link,0,sizeof(link));
scanf("%d%d",&m,&k);
while(k--)
{
scanf("%d%d%d",&p,&t1,&t2);
edge[t1+1][t2+1]=1; //下标全部+1,使得下标从1开始
}
int ans=0;
for(int i=2;i<=n;++i) // 忽略掉模式0
{
memset(vis,0,sizeof(vis)); //清空上次搜索时的标记
if(find(i)==true) //从节点i尝试扩展
ans++;
}
printf("%d\n",ans);
}
return 0;
}

posted on 2011-07-22 22:31  sysu_mjc  阅读(162)  评论(0编辑  收藏  举报

导航