poj1325Machine Schedule(二分匹配)

题目请戳这里

题目大意:2种机器A,B,A有n个工作模式0~n-1,B有m个工作模式0~m-1。一开始都工作在0模式,现在有k个工作,对于工作i可以工作在机器A的x模式或者B的y模式,机器切换模式要耗费时间,所以希望尽量少的切换模式。求机器完成k个工作最少的切换次数。

题目分析:根据题意很容易建一个二分图。顶点分别为机器A和机器B的工作模式,每个工作一条边。要求的就是这张图的最小点覆盖。而二分图的最小点覆盖=最大边独立即最大匹配,因此可以转化成二分图匹配问题。

trick:可以工作在0模式的工作免建图。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 105;
const int M = 1005;
int head[N];
int cx[N],cy[N];
struct edge
{
    int to,next;
}g[M];
bool flag[N];
int m,n;
void build(int s,int e,int num)
{
    g[num].to = e;
    g[num].next = head[s];
    head[s] = num;
}
int path(int u)
{
    int i;
    for(i = head[u];i != -1;i = g[i].next)
    {
        if(flag[g[i].to] == false)
        {
            flag[g[i].to] = true;
            if(cy[g[i].to] == -1 || path(cy[g[i].to]))
            {
                cy[g[i].to] = u;
                cx[u] = g[i].to;
                return 1;
            }
        }
    }
    return 0;
}
int maxmatch()
{
    int i;
    int ans = 0;
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    for(i = 1;i < n;i ++)
        if(cx[i] == -1)
        {
            memset(flag,false,sizeof(flag));
            ans += path(i);
        }
    return ans;
}
int main()
{
    int i,k;
    int a,b,c;
    while(scanf("%d",&n),n)
    {
        scanf("%d%d",&m,&k);
        memset(head,-1,sizeof(head));
        for(i = 1;i <= k;i ++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(b == 0 || c == 0)
                continue;
            build(b,c,i);
        }
        printf("%d\n",maxmatch());
    }
    return 0;
}
//128K	0MS


你可能感兴趣的:(图论,二分匹配)