HDU1150 二分匹配 最少点覆盖=最大匹配数

3个重要结论:

最小点覆盖数: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数
最小路径覆盖=最小路径覆盖=|N|-最大匹配数
用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。
二分图最大独立集=顶点数-二分图最大匹配
在N个点的图G中选出m个点,使这m个点两两之间没有边,求m最大值。
如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = N - 最大匹配数。


这里是第一个结论,最少的点(即覆盖数)=最大匹配数
题意:有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi。每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。

求的是最少点

#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>

#define ll long long
#define LL __int64
#define eps 1e-8
const ll INF=9999999999999;

using namespace std;

#define M 400000100

#define inf 0xfffffff

//vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p;

vector<int>G[1012];

int mp[1012][1012];
int marry[1012];
bool vis[1012];

int n,m;

void clear()
{
    memset(marry,-1,sizeof(marry));
    memset(mp,0,sizeof(mp));
    for(int i=0;i<1012;i++)
        G[i].clear();
}

bool dfs(int x)
{
    for(int i=0;i<m;i++)
    {
        if(mp[x][i] && !vis[i])
        {
            vis[i]=true;
            if(marry[i]==-1 || dfs(marry[i]))
            {
                marry[i]=x;
                return 1;
            }
        }
    }
    return 0;
}

int main(void)
{
    int k;
    while(scanf("%d",&n),n)
    {
        clear();
        scanf("%d %d",&m,&k);
        int u,v,w;
        for(int i=0;i<k;i++)
        {
            scanf("%d %d %d",&w,&u,&v);
            /*G[u].push_back(v);*/
            /*G[v].push_back(u);*/
            if(u>0 && v>0)//这里为什么请看poj1325的解题报告,有注释,连我自己都差点给忘了 错了半天
                mp[u][v]=1;
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            memset(vis,false,sizeof(vis));
            if(dfs(i))
                ans++;
        }
        printf("%d\n",ans);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值