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;
    }
}

总结

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

全部评论

相关推荐

04-16 10:27
已编辑
美团_Saas_后端开发
今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,拿到美团offer那会感觉自己天都亮了。没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
牛客48784610...:深圳的变成录用进行中,这个是稳了吗,还没有收到邮件
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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