poj 2446 poj 1469 poj 1274 二分图最大匹配

来源:互联网 发布:sqlserver置疑的原因 编辑:程序博客网 时间:2024/05/24 02:38

poj 2446:

题意:

给一张m * n的图,其中挖掉一些点,然后用1*2的小纸片来覆盖这张图,问能否将这个图覆盖。

如下图:

解析:

将每个不为挖掉的点视为二分图的X点集,这个点的四个方向上的点视为Y点集,此时最大匹配数即为点的个数(想一想为什么)。

因为有重复匹配 1和2

                             2和1

这题用一个id数组来处理每个点的id,然后用匈牙利算法求最大匹配就ok了。


代码:

(邻接矩阵版)1552K  172MS

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 33 * 33;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};bool maze[maxn][maxn];vector<int> g[maxn];bool vis[maxn];int fr[maxn];int m, n, k;int cnt;int id[maxn][maxn];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 <= cnt; i++)    {        memset(vis, false, sizeof(vis));        if (match(i))            ret++;    }    return ret;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d%d%d", &m, &n, &k))    {        memset(maze, true, sizeof(maze));        for (int i = 0; i < k; i++)        {            int x, y;            scanf("%d%d", &y, &x);            maze[x][y] = false;        }        if ((m * n - k) % 2)        {            printf("NO\n");        }        else        {            cnt = 0;            for (int i = 1; i <= m; i++)            {                for (int j = 1; j <= n; j++)                {                    if (maze[i][j])                    {                        id[i][j] = ++cnt;                    }                }            }            for (int i = 1; i <= m; i++)            {                for (int j = 1; j <= n; j++)                {                    if (maze[i][j])                    {                        for (int d = 0; d < 4; d++)                        {                            int ni = i + dir[d][0];                            int nj = j + dir[d][1];                            if (1 <= ni && ni <= m && 1 <= nj && nj <= n && maze[ni][nj])                            {                                g[id[i][j]].push_back(id[ni][nj]);                            }                        }                    }                }            }            //cout << hungary() <<endl;            if (hungary() + k == m * n)            {                printf("YES\n");            }            else            {                printf("NO\n");            }        }    }    return 0;}

(邻接表) 1492K       94MS

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 33 * 33;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};bool maze[maxn][maxn];bool vis[maxn];int fr[maxn];int m, n, k;int cnt;int id[maxn][maxn];struct edge{    int to, next;} e[maxn];int head[maxn];int index;void addedge(int u, int v){    e[index].to = v;    e[index].next = head[u];    head[u] = index;    index++;}bool match(int v){    for (int i = head[v]; i != -1; i = e[i].next)    {        int u = e[i].to;        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 <= cnt; i++)    {        memset(vis, false, sizeof(vis));        if (match(i))            ret++;    }    return ret;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d%d%d", &m, &n, &k))    {        memset(maze, true, sizeof(maze));        for (int i = 0; i < k; i++)        {            int x, y;            scanf("%d%d", &y, &x);            maze[x][y] = false;        }        if ((m * n - k) % 2)        {            printf("NO\n");        }        else        {            cnt = 0;            for (int i = 1; i <= m; i++)            {                for (int j = 1; j <= n; j++)                {                    if (maze[i][j])                    {                        id[i][j] = ++cnt;                    }                }            }            memset(head, -1, sizeof(head));            for (int i = 1; i <= m; i++)            {                for (int j = 1; j <= n; j++)                {                    if (maze[i][j])                    {                        for (int d = 0; d < 4; d++)                        {                            int ni = i + dir[d][0];                            int nj = j + dir[d][1];                            if (1 <= ni && ni <= m && 1 <= nj && nj <= n && maze[ni][nj])                            {                                addedge(id[i][j], id[ni][nj]);                            }                        }                    }                }            }            //cout << hungary() <<endl;            if (hungary() + k == m * n)            {                printf("YES\n");            }            else            {                printf("NO\n");            }        }    }    return 0;}

poj 1469:

题意:

给课程和喜欢这门课的学生。

问是否存在每个不同的学生喜欢不同的课。


解析:

最直接的二分图匹配。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 300 + 10;const int inf = 0x3f3f3f3f;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 p, n;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 angary(){    int ret = 0;    memset(fr, -1, sizeof(fr));    for (int i = 1; i <= p; i++)    {        memset(vis, false, sizeof(vis));        if (match(i))        {            ret++;        }    }    return ret;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int ncase;    scanf("%d", &ncase);    while (ncase--)    {        for (int i = 0; i < maxn; i++)            g[i].clear();        scanf("%d%d", &p, &n);        for (int i = 1; i <= p; i++)        {            int k;            scanf("%d", &k);            while (k--)            {                int x;                scanf("%d", &x);                g[i].push_back(x);            }        }    //    cout << angary() << endl;        if (angary() == p)            printf("YES\n");        else            printf("NO\n");    }    return 0;}


poj 1274

题意:

二分图最大匹配。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 200 + 10;const int inf = 0x3f3f3f3f;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    while (~scanf("%d%d", &n, &m))    {        for (int i = 0; i <= n; i++)            g[i].clear();        for (int i = 1; i <= n; i++)        {            int k;            scanf("%d", &k);            while (k--)            {                int x;                scanf("%d", &x);                g[i].push_back(x);            }        }        printf("%d\n", hungary());    }    return 0;}




0 0
原创粉丝点击