hdoj1150(最小点覆盖)

题意:
两台机器,A台机器有N种模式,B台机器有M种不同的模式,初始模式都是0
以及K个需要运行的任务(i,x,y),在A台机器是x模式,在B台机器是y模式。

请合理为每个任务安排一台机器并合理安排顺序,
每个任务要有对应A B机器的模式中至少要有一种来运行
每次切换都会付出代价1,使得代价最小,
- -求出这个最小值。

思路:
这很明显是有张二分图。
点:A模式,B模式;
边:job_k可由机器A的模式i转化成机器B的模式j(可以理解是任务)
那么问题就转化成是否存在一个最小点集,使得所有的边都至少和该点集的一个点相联系。
这就是最小顶点覆盖数

补:点覆盖、最小点覆盖、最小顶点覆盖数
点覆盖集即一个点集,使得所有边至少有一个端点在集合里。
或者说是“点” 覆盖了所有“边”。
极小点覆盖(minimal vertex covering):本身为点覆盖,其真子集都不是。
最小点覆盖(minimum vertex covering):点最少的点覆盖。点覆盖数(vertex covering number):最小点覆盖的点数。
=最大匹配数

其实这题对于本萌新而言是这个最小点覆盖的问题
二分图求最小顶点覆盖:
即用最少的顶点个数可以让每条边至少与其中一个点关联

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <math.h>
#include <queue>
#include <stack>
using namespace std;
#define INF 0x3f3f3f
#define pi acos(-1.0)
#define LL long long
#define N 550

int ma[N][N];
int cx[N],cy[N];
int vis[N];
int k,m,n;

int fuck(int u)
{
    for(int i=0; i<m; i++)
    {
        if(!vis[i]&&ma[u][i])
        {
            vis[i]=1;
            if(cy[i]==-1||fuck(cy[i]))
            {
                cy[i]=u;
                return 1;
            }
        }
    }
    return 0;
}


int main()
{
    while(~scanf("%d",&n)&&n)
    {
        int a,b;
        scanf("%d%d",&m,&k);
        memset(ma,0,sizeof(ma));
        int x;
        for(int i=0; i<k; i++)
        {
            scanf("%d%d%d",&x,&a,&b);
            if(a>0&&b>0)            //初始状态为0,一开始0的边不要加
                ma[a][b]=1;
        }
        memset(cy,-1,sizeof(cy));

        int ans=0;
        for(int i=0; i<n; i++)
        {
            memset(vis,0,sizeof(vis));
            if(fuck(i))
            {
                ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2016-05-16 22:28  see_you_later  阅读(195)  评论(0编辑  收藏  举报