POJ - 1087【匈牙利匹配】

A Plug for UNIX

题意:

房间里有n个不同的插口,有m个设备,每个设备对应一种插口。有k个插口转换器(a, b:表示该转换器可以将插口b转为a),转换器可以插在对应的初始的n个插口,也可以插在对应的转换器上。要使得设备匹配插口最大,求未能匹配的设备数量。(转换器的数量无限)

思路:

如果一个设备对应的插口x可以由转换器级联得到,那么该设备实际上是对应了所有和x在一个网络中的插口。
所以我们根据所有k组转换器信息做成一个有向图(由a指向b),这样的话我们从每个设备对应的插口进行深搜,即可得到设备对应的所有直接或者间接可行插口。
然后每个设备就有了对应的可行插口,再和已有的n个插口进行二分图最大匹配就可以得到最后的答案。

Code:
#include <iostream>
#include <cstdio>
#include <set>
#include <map>
#include <cstring>
#include <string>

using namespace std;

int read()
{
    
    
    int x = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9') {
    
     if(ch == '-') f = -f; ch = getchar(); }
    while(ch >= '0' && ch <= '9') {
    
     x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

const int maxN = 305;
int n, m, k, has[maxN];
string havePlug[maxN];
string needPlug[maxN];
struct Change{
    
    
    string to, from;
}change[maxN];

int nodeTot;
map<string, int>number;

int head[maxN], cnt;
struct EDGE{
    
    
    int adj, to;
    EDGE(int a = -1, int b = 0): adj(a), to(b) {
    
    }
}edge[maxN];
void add_edge(int u, int v)
{
    
    
    edge[cnt] = EDGE(head[u], v);
    head[u] = cnt ++ ;
}

bool match[maxN][maxN];
int used[maxN], l[maxN];
void init() {
    
     for(int i = 1; i <= nodeTot; ++ i ) used[i] = has[i]; }
void getMatch(int u, int x)
{
    
    
    match[x][u] = true;
    for(int i = head[u]; ~i; i = edge[i].adj ) {
    
    
        int v = edge[i].to;
        getMatch(v, x);
    }
}
bool Hungary(int x)
{
    
    
    for(int j = 1; j <= nodeTot; ++ j ) {
    
    
        if(match[x][j] && used[j]) {
    
    
            -- used[j];
            if(l[j] == 0 || Hungary(l[j])) {
    
    
                l[j] = x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    
    
    n = read();
    for(int i = 1; i <= n; ++ i ) {
    
    
        cin >> havePlug[i];
        if(!number[havePlug[i]]) number[havePlug[i]] = ++ nodeTot;
    }
    m = read();
    for(int i = 1; i <= m; ++ i ) {
    
    
        string device;
        cin >> device >> needPlug[i];
        if(!number[needPlug[i]]) number[needPlug[i]] = ++ nodeTot;
    }
    k = read();
    for(int i = 1; i <= k; ++ i ) {
    
    
        cin >> change[i].to >> change[i].from;
        if(!number[change[i].to]) number[change[i].to] = ++ nodeTot;
        if(!number[change[i].from]) number[change[i].from] = ++ nodeTot;
    }
    memset(head, -1, sizeof(head));
    for(int i = 1; i <= k; ++ i ) {
    
    
        int u = number[change[i].to], v = number[change[i].from];
        add_edge(u, v);
    }
    for(int i = 1; i <= m; ++ i ) {
    
    
        getMatch(number[needPlug[i]], i);
    }
    for(int i = 1; i <= n; ++ i ) {
    
    
        ++ has[number[havePlug[i]]];
    }
    int ans = m;
    for(int i = 1; i <= m; ++ i ) {
    
    
        init();
        if(Hungary(i)) -- ans;
    }
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/106817090