POJ 2289 Jamie's Contact Groups

大意不再赘述。

思路:二分图最大多重匹配,可用二分枚举实现。呜呜呜,有一个BUG害我找了好久哦。。。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <stack>
using namespace std;

const int MAXN = 1010;
const int MAXM = 1010*510;

struct Edge
{
	int v;
	int next;
}edge[MAXM];

int nx, ny;
int cnt;
int limit;

int first[1010];
bool vis[1010];
int vylink[1010];
int ylink[510][1010];

void init()
{
	cnt = 0;
	memset(first, -1, sizeof(first));
}

void read_graph(int u, int v)
{
	edge[cnt].v = v;
	edge[cnt].next = first[u], first[u] = cnt++;
}

int find(int u)
{
	int i, j;
    for(int e = first[u]; e != -1; e = edge[e].next)
    {
		i = edge[e].v;
        if(!vis[i])
        {
            vis[i] = 1;
            if(vylink[i] < limit)
            {
                ylink[i][vylink[i]++] = u;
                return 1;
            }
            for(j = 0; j < vylink[i]; j++)
                if(find(ylink[i][j]))
                {
                    ylink[i][j] = u;
                    return 1;
                }
        }
	}
	return 0;
}
 
 bool MulMatch()
 {
     memset(vylink, 0, sizeof(vylink));
     for(int i = 0; i < nx; i++)
     {
         memset(vis , 0, sizeof(vis));
         if(!find(i)) return 0;
     }
     return 1;
 }

void BSearch()
{
	int x = 0, y = nx;
	while(x <= y)
	{
		limit = (x+y)/2;
		if(MulMatch()) y = limit-1;
		else x = limit+1;
	}
	printf("%d\n", x);
}

void read_case()
{
	init();
	char str[3020];
	for(int i = 0; i < nx; i++)
	{
		gets(str);
		for(int j = 0; j < strlen(str); j++) if(isdigit(str[j]))
		{ // for(int j = 0; str[j]; j++) 报错了,scanf("%s", str)才能用 
			int v = 0;
			while(isdigit(str[j]))
			{
				v = v*10 + str[j++]-'0';
			}
			read_graph(i, v);
		}
	}
}

void solve()
{
	read_case();
	BSearch();
}

int main()
{
	while(scanf("%d%d%*c", &nx, &ny) && (nx || ny))
	{
		solve();
	}
	return 0;
}


你可能感兴趣的:(POJ 2289 Jamie's Contact Groups)