zoukankan      html  css  js  c++  java
  • B

    题意:现在有一些学生给你一下朋友关系(不遵守朋友的朋友也是朋友),先确认能不能把这些人分成两组(组内的人要相互不认识),不能分的话输出No(小写的‘o’ - -,写成了大写的WA一次),能分的话,在求出来一对朋友可以住一个房间,最多可以开多少双人房(- -)
    分析:使用并查集分组,如果出现矛盾就是不能分,可以分的话再用一组的成员求出最大匹配就OK了,还是比较水的....
    *******************************************************************
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;

    const int MAXN = 205;

    ///rl记录与根节点的关系
    int fa[MAXN], rl[MAXN];
    int FindFather(int x)
    {
        int k = fa[x];
        if(fa[x] != x)
        {
            fa[x] = FindFather(fa[x]);
            rl[x] = (rl[x]+rl[k]) % 2;
        }

        return fa[x];
    }

    int x[MAXN], y[MAXN], nx, N;
    bool G[MAXN][MAXN], used[MAXN];

    void InIt()
    {
        nx = 0;
        memset(G, 0sizeof(G));
        for(int i=0; i<MAXN; i++)
        {
            fa[i] = i;
            x[i] = y[i] = 0;
            rl[i] = 0;
        }
    }
    bool FindOk(int u)
    {
        for(int i=1; i<=N; i++)
        {
            if(G[u][i] && used[i] == false)
            {
                used[i] = true;
                if(!y[i] || FindOk(y[i]))
                {
                    y[i] = u;
                    return true;
                }
            }
        }

        return false;
    }

    int main()
    {
        int M;

        while(scanf("%d%d", &N, &M) != EOF)
        {
            int i, u, v, ok=0;

            InIt();

            while(M--)
            {
                scanf("%d%d", &u, &v);
                G[u][v] = G[v][u] = true;

                int ru = FindFather(u);
                int rv = FindFather(v);

                if(ru == rv && rl[u] == rl[v])
                    ok = 1;
                else if(ru != rv)
                {
                    fa[ru] = rv;
                    rl[ru] = (rl[u]+rl[v]+1)%2;
                }
            }

            if(ok)
                printf("No ");
            else
            {
                for(i=1; i<=N; i++)
                {
                    u = FindFather(i);
                    if(rl[i] == 0)
                        x[nx++] = i;
                }

                int ans = 0;
                for(i=0; i<nx; i++)
                {
                    memset(used, falsesizeof(used));
                    if(FindOk(x[i]) == true)
                        ans++;
                }

                printf("%d ", ans);
            }
        }

        return 0; 

    }

  • 相关阅读:
    【BZOJ1345】[Baltic2007] 序列问题(单调栈大水题)
    【BZOJ2940】[POI2000] 条纹(Multi-SG)
    【BZOJ4589】Hard Nim(FWT+快速幂)
    【CF438E】The Child and Binary Tree(生成函数+多项式开根)
    【洛谷5205】【模板】多项式开根
    【BZOJ4036】[HAOI2015] 按位或(Min-Max容斥+FWT)
    【BZOJ4381】[POI2015] ODW(设阈值+倍增)
    【BZOJ3328】PYXFIB(矩乘+单位根反演)
    【BZOJ2674】Attack(整体二分+树状数组套线段树)
    单纯看懂公式的单位根反演
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4694380.html
Copyright © 2011-2022 走看看