HDU

来源:互联网 发布:收集5条红酒网络广告语 编辑:程序博客网 时间:2024/06/05 04:50

题目链接: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;}
原创粉丝点击