hdu1083 二分图最大匹配模板

版权声明:转载请注明出处 https://blog.csdn.net/jay__bryant/article/details/82262094

增广路的性质:
(1)整条路径上没有重复的点。起点在二分图的左半边,终点在右半边,并且左右交替出现。
(2)起点和终点都是未配对的,除起点和终点外其它所有点都是已经配好对的。
(4)有奇数条边。
(5)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。
(6)把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原
匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。

匈牙利算法 O(VE)

#include <cstdio>
#include <cstring>

using namespace std;
const int N = 310;
int g[N][N];
int linker[N];
int L, R;
bool vis[N];

bool dfs(int l)
{
    for(int r = 1; r <= R; ++r)
        if(g[l][r] && !vis[r])
        {
            vis[r] = 1;
            if(linker[r]==-1 || dfs(linker[r]))
            {
                linker[r] = l;
                return 1;
            }
        }
    return 0;
}

int hungary()
{
    int ret = 0;
    memset(linker, -1, sizeof(linker));
    for(int l = 1; l <= L; ++l)
    {
        memset(vis, 0, sizeof(vis));
        if(dfs(l))
            ++ret;
    }
    return ret;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %d", &L, &R);
        memset(g, 0, sizeof(g));
        for(int l = 1; l <= L; ++l)
        {
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; ++i)
            {
                int r;
                scanf("%d", &r);
                g[l][r] = 1;
            }
        }
        if(hungary()==L) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

vector优化:处理点数较多的情况(n>1000)

#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
const int N = 310;
vector <int> g[N];
int linker[N];
int L, R;
bool vis[N];

bool dfs(int l)
{
    for(int i = 0; i < g[l].size(); ++i)
        if(!vis[g[l][i]])
        {
            vis[g[l][i]] = 1;
            if(linker[g[l][i]]==-1 || dfs(linker[g[l][i]]))
            {
                linker[g[l][i]] = l;
                return 1;
            }
        }
    return 0;
}

int hungary()
{
    int ret = 0;
    memset(linker, -1, sizeof(linker));
    for(int l = 1; l <= L; ++l)
    {
        memset(vis, 0, sizeof(vis));
        if(dfs(l))
            ++ret;
    }
    return ret;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        for(int i = 0; i < N; ++i) g[i].clear();
        scanf("%d %d", &L, &R);
        memset(g, 0, sizeof(g));
        for(int l = 1; l <= L; ++l)
        {
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; ++i)
            {
                int r;
                scanf("%d", &r);
                g[l].push_back(r);
            }
        }
        if(hungary()==L) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/82262094