zoukankan      html  css  js  c++  java
  • H

    题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚。
    分析:先求出来他们的最大匹配,因为给的数据未必是完备匹配,所以需要添加一些点使他们成为完备匹配才能求出来的环是完整的,比如第二组数据:
    1 2  
    2 1 2
    如果不添加虚拟点做成匹配,只会匹配成功一个,这样就找不出来环了,所以需要添加虚拟的王子和公主,虚拟的王子喜欢所有的公主,虚拟的公主被所有的王子喜欢,注意都是王子喜欢公主的,公主没有选择喜欢的权利(确实有点悲哀- -)
    *************************************************************************
    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<algorithm>
    using namespace std;

    const int MAXN = 2005;
    const int Base = 500;
    ///base 王子的编号从1开始 公主的编号从base+1开始, 虚拟点的编号从base*2+1开始
    int N, M;
    bool love[1005][1005];
    vector< vector <int> >ans;
    /***************邻接表*********************/
    struct Edge{int v, next;}e[MAXN*MAXN];
    int Head[MAXN], cnt;

    void AddEdge(int u, int v)
    {
        e[cnt].v = v;
        e[cnt].next = Head[u];
        Head[u] = cnt++;
    }
    /**************Tarjan**********************/
    int dfn[MAXN], low[MAXN], Index;
    int Stack[MAXN], instack[MAXN], top;
    int belong[MAXN], bnt;

    void Tarjan(int i)
    {
        int v;

        dfn[i] = low[i] = ++Index;
        Stack[++top] = i, instack[i] = true;

        for(int j=Head[i]; j!=-1; j=e[j].next)
        {
            v = e[j].v;

            if( !dfn[v] )
            {
                Tarjan(v);
                low[i] = min(low[i], low[v]);
            }
            else if( instack[v] )
                low[i] = min(low[i], dfn[v]);
        }

        if(low[i] == dfn[i])
        {
            ++bnt;
            do
            {
                v = Stack[top--];
                instack[v] = false;
                belong[v] = bnt;
                if(v > Base)
                    ans[bnt].push_back(v-Base);
            }
            while(i != v);
        }
    }
    /***************匈牙利********************/
    int Lx[MAXN], Ly[MAXN];
    bool used[MAXN];

    bool Find(int i)
    {
        for(int j=Head[i]; j!=-1; j=e[j].next)
        {
            int v = e[j].v;

            if( !used[v] )
            {
                used[v] = true;
                if( !Ly[v] || Find(Ly[v]) )
                {
                    Ly[v] = i;
                    Lx[i] = v;

                    return true;
                }
            }
        }

        return false;
    }
    void XYL()///顺便添加虚拟点
    {
        int i, j, k, sum=0;

        for(i=1; i<=N; i++)
        {
            memset(used, falsesizeof(used));
            sum += Find(i);
        }

        k = Base * 2 + 1;///虚拟点开开始处

        for(i=1; i<=N; i++)
        {///遍历王子部分,看那个王子没有匹配,为他虚拟一个公主,这个公主所有的王子都喜欢
            if(Lx[i] == false)
            {
                Lx[i] = k;
                Ly[k] = i;

                for(j=1; j<=N; j++)
                    AddEdge(j, k);
                k++;
            }
        }



        for(i=Base+1; i<=Base+M; i++)
        {///遍历公主部分,看哪个公主没有匹配,为她虚拟一个王子,这个王子喜欢所有的公主
            if(Ly[i] == false)
            {
                Lx[k] = i;
                Ly[i] = k;

                for(j=Base+1; j<=Base+M; j++)
                    AddEdge(k, j);
                k++;
            }
        }


        for(i=Base+1; i<k; i++)
        {///匹配的点添加反边
            AddEdge( i, Ly[i] );
        }
    }

    /***************初始化********************/
    void InIt()
    {
        ans.clear();
        ans.resize(MAXN);

        memset(love, falsesizeof(love));
        memset(dfn, falsesizeof(dfn));
        memset(Head, -1sizeof(Head));
        memset(Lx, falsesizeof(Lx));
        memset(Ly, falsesizeof(Ly));

        cnt = Index = bnt = 0;
    }
    /******************************************/
    int main()
    {
        int T, t=1;

        scanf("%d", &T);

        while(T--)
        {
            int i, j, v, Len;

            scanf("%d%d", &N, &M);
            InIt();

            for(i=1; i<=N; i++)
            {
                scanf("%d", &Len);

                while(Len--)
                {
                    scanf("%d", &v);
                    AddEdge(i, v+Base);
                    love[i][v] = true;
                }
            }

            XYL();

            for(i=1; i<=N; i++)
            {
                if( !dfn[i] )
                    Tarjan(i);
            }

            printf("Case #%d: ", t++);
            for(i=1; i<=N; i++)
            {
                v = belong[i];
                Len = ans[v].size();

                int a[MAXN], k=0;

                for(j=0; j<Len; j++)
                {///王子必须喜欢这个公主才行
                    if(love[i][ ans[v][j] ] == true)
                        a[k++] = ans[v][j];
                }

                sort(a, a+k);

                printf("%d", k);
                for(j=0; j<k; j++)
                    printf(" %d", a[j]);
                printf(" ");
            }
        }

        return 0; 

    }

  • 相关阅读:
    浏览器加载AMD标准的输出文件
    Mac安装brew && brew 安装yarn
    插件集
    vue-router复用组件时不刷新数据
    加入sass后运行项目报错:TypeError: this.getResolve is not a function
    安装cnpm后运行报cnpm : 无法加载文件 C:UsersyizonAppDataRoaming pmcnpm.ps1,因为在此系统上禁止运行脚本
    图片canvas跨域问题解决方案之一
    vscode配置
    搭建express服务
    项目初始化
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4709705.html
Copyright © 2011-2022 走看看