POJ1719行列匹配

题意:
     给一个n*m的格子,每一列都有两个白色的,其余的全是黑色的,然后要选择m个格子,要求是每一列必须也只能选一个,而每一行至少选择一个,输出一种可行的方案没,输出的格式是输出m个数,表示每一列上选了第几行的数。


思路: 
     一开始看到每一行至少选择一个,都点蒙了,后来自己画了下,哎!SB了,比较简单的题目,题目的输入数据是说n<=m,那么也就是指存在两种情况,n=m和n<m,当n=m的时候就是每一行每一列至少也只能选一个,直接匹配就行了,而当n<m的时候也就是说每一个行至少一个,有的比一个多,那么我们就先用二分匹配给每一行都安排一个,然后剩下的没有安排的列,我们只要随便给挑一个就行了。


#include<stdio.h>
#include<string.h>


#define N_node 1000 + 10
#define N_edge 2000 + 20


typedef struct
{
    int to ,next;
}STAR;


typedef struct
{
    int a ,b;
}NODE;


STAR E[N_edge];
NODE node[N_node];
int list[N_node] ,tot;
int mkgx[N_node] ,mkdfs[N_node];


void add(int a ,int b)
{
    E[++tot].to = b;
    E[tot] .next = list[a];
    list[a] = tot;
}


int DFS_XYL(int x)
{
    for(int k = list[x] ;k ;k = E[k].next)
    {
        int to = E[k].to;
        if(mkdfs[to]) continue;
        mkdfs[to] = 1;
        if(mkgx[to] == -1 || DFS_XYL(mkgx[to]))
        {
            mkgx[to] = x;
            return 1;
        }
    }
    return 0;
}


int main ()
{
    int t ,n ,m ,i ,j;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d %d" ,&n ,&m);
        memset(list ,0 ,sizeof(list));
        for(i = 1 ;i <= m ;i ++)
        {
            scanf("%d %d" ,&node[i].a ,&node[i].b);
            add(node[i].a ,i);
            add(node[i].b ,i);
        }
        int Ans = 0;
        memset(mkgx ,255 ,sizeof(mkgx));
        for(i = 1 ;i <= n ;i ++)
        {
            memset(mkdfs ,0 ,sizeof(mkdfs));
            Ans += DFS_XYL(i);
        }
        if(Ans < n)
        {
            printf("NO ");
            continue;
        }
        for(i = 1 ;i <= m ;i ++)
        {
            if(mkgx[i] == -1) Ans = node[i].a;
            else Ans = mkgx[i];
            if(i == m) printf("%d " ,Ans);
            else printf("%d " ,Ans);
        }
    }
    return 0;
}







原文地址:https://www.cnblogs.com/csnd/p/12062478.html