HDU 1150 浅谈二分图最小点覆盖水题

本文介绍了一种利用二分图的最大匹配算法解决机器重启次数最少的问题。通过为两个机器及其任务建立二分图模型,实现了在完成所有任务的前提下,机器重启次数的最小化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述
世界真的很大
这道题基本上还是比较简单,怎么感觉最近老是在做水题。。
不要在意,即使是水题也有可以总结的地方
抱着这样的感觉来写博客。。
但是感觉字数什么的会很少吧。。

看题先:

description:

有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式ai,如果它在机器B上运行,则机器B需要设置为模式bi。每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。

input:

The input file for this program consists of several configurations. The first line of one configuration contains three positive integers: n, m (n, m < 100) and k (k < 1000). The following k lines give the constrains of the k jobs, each line is a triple: i, x, y.

The input will be terminated by a line containing a single zero.

output:

The output should be one integer per line, which means the minimal times of restarting machine.

唔。。
题目要求重启次数最少,即是说想要需要的模式总数最少。
就是说想要用最少的模式完成所有的任务
每个任务可以被A,B两台机器的两种模式分别完成
“最少的什么什么”“完成/覆盖什么什么”“两种”
关键字已经出来了,二分图的最小点覆盖

每个任务让A的模式对B的模式连边,这样就是一个二分图,求一个最大匹配即最小点覆盖就好

需要注意的是,我们求出的是最少的模式数,如果其中包含了0模式那么答案就要减1,因为一开始就是0模式,不需要额外重启

完整代码:

#include<stdio.h>
#include<cstring>
using namespace std;

struct edge
{
    int v,last;
}ed[400010];

int n,m,K,num=0,ans=0,tot=0;
int head[100010],book[100010],match[100010];

void add(int u,int v)
{
    num++;
    ed[num].v=v;
    ed[num].last=head[u];
    head[u]=num;
}

int dfs(int u)
{
    for(int i=head[u];i;i=ed[i].last)
    {
        int v=ed[i].v;
        if(book[v]!=tot)
        {
            book[v]=tot;
            if(!match[v] || dfs(match[v]))
            {
                match[u]=v,match[v]=u;
                return 1;
            }
        }
    }
    return 0;
}

void init()
{
    memset(match,0,sizeof(match));
    memset(head,0,sizeof(head));
    memset(book,0,sizeof(book));
    num=ans=tot=0;
}

int main()
{
    while(1)
    {
        init();
        scanf("%d",&n);
        if(!n) break ;
        scanf("%d%d",&m,&K);
        while(K--)
        {
            int x,u,v;
            scanf("%d%d%d",&x,&u,&v);
            add(u,v+n),add(v+n,u);
        }
        for(int i=0;i<n+m;i++)
        {
            tot++;
            if(!match[i]) ans+=dfs(i);
        }
        if(match[0]) ans--;
        if(match[n]) ans--;
        if(match[0]==n) ans++;
        printf("%d\n",ans);
    }
    return 0;
}
/*
EL PSY CONGROO
*/

嗯,就是这样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值