1. 程式人生 > >hdu 1150 二分圖最大匹配最小點覆蓋

hdu 1150 二分圖最大匹配最小點覆蓋

題意:

有兩臺機器A和B以及k個需要執行的任務。每臺機器有n,m種不同的模式,而每個任務都恰好能在一臺機器上執行。

機器A上有模式 mode_0, mode_1, …, mode_n-1,機器B上有模式: mode_0, mode_1, … , mode_m-1。

開始的工作模式都是mode_0。每個任務有對應的執行模式,(i, x, y)表示i任務對應的A B機器上的執行模式mode_x, mode_y。

每臺機器上的任務可以按照任意順序執行,但是每臺機器每轉換一次模式需要重啟一次。

合理安排順序,使得機器充氣次數最少。問最少是多少次。

解析:

每次來一個任務就加一條向AB機器模式fr,to的邊,最後的最小點覆蓋即為所求。

這題有個坑點是起始的時候機器的工作模式是0,所以有0模式的就沒必要要加入點集了。。。

樣例你是故意的- -

程式碼:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100 + 10;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

vector<int> g[maxn];
int fr[maxn];
bool vis[maxn];
int n, m;

bool match(int v)
{
    for (int i = 0; i < g[v].size(); i++)
    {
        int u = g[v][i];
        if (!vis[u])
        {
            vis[u] = true;
            if (fr[u] == -1 || match(fr[u]))
            {
                fr[u] = v;
                return true;
            }
        }
    }
    return false;
}

int hungary()
{
    int ret = 0;
    memset(fr, -1, sizeof(fr));
    for (int i = 1; i < n; i++)
    {
        memset(vis, false, sizeof(vis));
        if (match(i))
        {
            ret++;
        }
    }
    return ret;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif // LOCAl
    int k;
    while (~scanf("%d", &n) && n)
    {
        scanf("%d%d", &m, &k);
        for (int i = 0; i <= n; i++)
        {
            g[i].clear();
        }
        while (k--)
        {
            int t, fr, to;
            scanf("%d%d%d", &t, &fr, &to);
            if(fr && to)
                g[fr].push_back(to);
        }
        printf("%d\n", hungary());
    }
    return 0;
}