您的位置:首页 > 其它

HDU - 1150 : Machine Schedule(二分图、最小点覆盖)

2017-08-24 14:12 323 查看
题目链接:HDU - 1150 : Machine Schedule

题目大意:有A和B两台机器,A有n种工作模式,B有m种工作模式,现在有k个任务,每个任务可以被A的第x种模式执行,也可以被B的第y种模式执行,机器的初始工作状态在0模式,但是机器每换一种工作模式就需要重启一次,现在请你合理为机器安排任务,使得重启次数最少

题目分析:这里我们把每个任务看成一条边,A机器的每个模式看成cx的节点,B机器的每个模式看成cy的节点,这样就构成了一个二分图,题目要求重启次数最少,也即使用不同模式的次数最少,由此转化为最小点覆盖问题,由二分图性质可知,最小点覆盖数=最大匹配数,题目有个坑,就是注意机器的初始模式已经设定为0模式,因此与0模式相连的任务不能作为边。

AC代码:

//匈牙利算法

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=110;
int graph[maxn][maxn],vis[maxn];//图G和增广路访问标记
int match[maxn];//左边元素对应右边的匹配
int nx,ny,m;//左边点数,右边点数,边数

bool find_path(int u)//找增广路
{
for(int i=0; i<ny; i++)
{
if(graph[u][i] && !vis[i])//不在增广路
{
vis[i]=1;//放进增广路
if(match[i]==-1 || find_path(match[i]))//判断cy[i]是否匹配过,如果匹配过,则试图更改它之前的匹配项
{//用dfs搜索,如果之前的匹配项能另外还存在增广路,则这里可以匹配u
match[i]=u;
return true;
}
}
}
return false;
}

int max_match()
{
int res=0;
memset(match,-1,sizeof(match));
for(int i=0; i<nx; i++)
{
memset(vis,0,sizeof(vis));
if(find_path(i)) res++;
}
return res;
}

int main()
{
while(scanf("%d",&nx)==1 && nx)
{
scanf("%d%d",&ny,&m);
memset(graph,0,sizeof(graph));
for(int i=1; i<=m; i++)
{
int id,x,y;
scanf("%d%d%d",&id,&x,&y);//本题的x,y编号是从0开始
if(x && y) graph[x][y]=1;//注意,机器的起始状态处于0模式,故不能算作一次
}
printf("%d\n",max_match());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: