Machine Schedule

题目链接

http://poj.org/problem?id=1325

题目大意

k个工作(从0开始编号),a机器n个模式(模式从0开始编号),b机器有m个模式(模式从0开始编号);
每个工作都可以由机器a的一个模式或机器b的一个模式完成且只能由机器a的一个模式或机器b的一个模式完成;
按一定顺序安排完成工作的顺序,使得切换机器的次数最少,求最少的切换机器次数;
最开始机器a和机器b都处于0模式

解题思路

建图:

将每个工作需要的两个种机器模式连边,那么每一条边就代表一种工作;左集合是一条边的一个端点,右集合是此边的另一个端点。
建好图了就比较好想了,要将所有工作都完成,就意味着要把所有的边全部覆盖;这就是二分图最小点覆盖问题,也就可以转化为二分图最大匹配数。

为什么这么建图?

说实话,我没想到,直接把题意理解错了。
我们可以这么试着理解:
对于一个工作,要么选a机器的模式,要么选b机器的模式,也就是说,对于一个工作而言,不可能既选a机器的模式完成的它,又选b机器的模式完成它,这样必然不是最小点覆盖。类似这种不能同时选的,我们自然想把不能同时选的放到两个不同的集合中,这就是为什么要将一个工作的a机器模式和b机器模式连边。
只要覆盖住了每条边就代表完成了全部的工作。

注意

注意“最开始机器a和机器b处于0模式”,
意味着可以通过a机器的0模式或者b机器的0模式完成的任务,可以在不切换模式的情况下完成,所以不能访问与a或b的0模式相连的边,因为不需要覆盖这条边了,这条边已经被覆盖过了。
至于“最小点覆盖=最大匹配数”的证明,读者自己百度吧,我感觉挺难的,不会。
看代码吧!

AC代码

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N=110;
const int M=1005;
vector<int> e[N];
int n,m,k,cnt,vis[N],link[N],job,ma,mb;

bool dfs(int x)
{
    for(int i=0;i<e[x].size();i++)
    {
        int v=e[x][i];
        if(vis[v] || v==0) continue;//必须不能访问b机器的0模式 
        vis[v]=1;
        if(link[v]==0 || dfs(link[v]))
        {
            link[v]=x;
            return 1;
        }
    }
    return 0;
}

int main()
{
    while(~scanf("%d",&n))
    {
        if(n==0) break;
        scanf("%d%d",&m,&k);
        memset(link,0,sizeof link);
        cnt=0;
        for(int i=0;i<n;i++) e[i].clear();

        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&job,&ma,&mb);
            e[ma].push_back(mb);//你也可以在这里判断一下,在mb!=0的前提下push_back,这样你就不用在dfs中continue掉v==0的情况了
        }
        for(int i=1;i<n;i++)//必须是从a机器的1模式开始 
        {
            memset(vis,0,sizeof vis);
            if(dfs(i)) cnt++;
        }
        cout<<cnt<<endl;
    }
}

总结

我觉得二分图的匈牙利算法还是需要时间沉淀;
自己对二分图的理解不是很透彻导致不会建图,同时对匈牙利算法的理解也不够深刻,导致实现代码的时候会漏掉细节。

全部评论

相关推荐

来,说点可能被同行“骂”的大实话。🙊当初接数字马力Offer时,朋友都说:“蚂蚁的“内包”公司?你想清楚啊!”但入职快一年后的今天,我反而对他有了不一样的看法!🔹&nbsp;是偏见?还是信息差!之前没入职之前外面都在说什么岗位低人一等这类。实际上:这种情况不可至否,不能保证每个团队都是其乐融融。但我在的部门以及我了解的周边同事都还是十分好相处的~和蚂蚁师兄师姐之间也经常开一些小玩笑。总之:身份是蚂蚁公司给的,地位是自己挣的(一个傲娇女孩的自述)。🔹&nbsp;待遇?玩的就是真实!试用期工资全额发!六点下班跑得快(早9晚6或者早10晚7,动态打卡),公积金顶格交。别听那些画饼的,到手的钱和下班的时间才是真的(都是牛马何必难为牛马)。🔹&nbsp;能不能学到技术?来了就“后悔”!我们拥有权限直通蚂蚁知识库,技术栈多到学不完。说“学不到东西”的人,来了可能后悔——后悔来晚了(哈哈哈哈,可以不学但是不能没有)!💥&nbsp;内推地址:https://app.mokahr.com/su/ueoyhg❗我的内推码:NTA6Nvs走我的内推,可以直达业务部门,面试流程更快速,进度可查!今天新放HC,之前挂过也能再战!秋招已经正式开始啦~机会就摆在这,敢不敢来试一试呢?(和我一样,做个勇敢的女孩)
下午吃泡馍:数字马力的薪资一般哇,5年经验的java/测试就给人一万出头,而且刚入职第三天就让人出差,而且是出半年
帮你内推|数字马力 校招
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务