D、 Largest Group
One day your university decided to run some statistics. They wanted to study friendship relations among boys and girls, and its effectiveness on their grades.
Strange thing about your university is that it has the exact same number of boys and girls. More formally, the university has P boys numbered from 1 to P, and P girls numbered from 1 to P.
We know that any pair of boys are surely friends, and any pair of girls are definitely friends. However, boys and girls are not always friends. To be precise, the university has a list of length N containing the friendship relations between girls and boys. the ith friendship relation is described by two integers bi and gimeaning that the boy number bi and girl number gi are friends.
One of the statistics your university is interested in, is the largest group of people (boys and girls) where any pair of them are friends. Can you write a program that would solve such a problem?
Input
The first line contains an integer T, the number of test cases.
Each test case starts with a line containing 2 space separated integers P and Ndenoting both the number of boys and girls at your university, and the number of friendship relations. (1 ≤ P ≤ 20), (0 ≤ N ≤ P2).
N lines follow. The ith line of them contains 2 space separated integers bi, gidescribing a friendship relation.
Output
For each test case print a single line, containing a single integer, denoting the number of people in the largest group where any pair of people among them are friends.
Example
Input
2 4 5 1 2 2 2 3 2 4 2 1 4 3 4 1 2 2 1 1 1 2 2
Output
5 4
一、原题地址
二、大致题意
现在有P个男生和P个女生,他们之间存在n个关系,每对关系用 ai 和 bj 来表示第 i 个男生和第 j 个女生相识。
默认已知所有男生互相认识,所有女生也互相认识,现在要求找出一个团体,这个团体满足集合内所有的人都互相认识(也就是构成了完全图)。
求这个团体内集合元素的最大值。
三、思路
原本写了一大坨的爆搜程序三重的判断试图来跑出数据量只有40的答案,TLE了之后非常绝望。之后发现是一道结论题。这样寻找最大完全图的问题大家把这个叫做最大团。
二分图的最大团 = 它补图的最大独立集。
二分图最大团的定义是:一个最大的点的集合,该集合内的任意两点都有边相连。
二分图的最大独立集是:一个最大的点的集合,该集合内的任意两点没有边相连。
而补图的最大独立集 = 二分图顶点数 - 二分图最大匹配数。
然后问题就转化为了求这个二分图的补图的最大匹配数。这样就很简单啦.我使用的是匈牙利算法来求匹配数。
四、代码
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <cstdio>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
#define LL long long
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
LL gcd(LL a, LL b) { return b ? gcd(b, a%b) : a; }
const int maxv = 1011;
int T;
int P, N;
int uN;
int match[100];
bool visit[100];
bool vec[100][100];
int find(int u)
{
for (int i = 21; i <= 20 + P; i++)
{
if (vec[u][i]&&!visit[i])
{
visit[i] = 1;
if (match[i] == -1 || find(match[i]))
{
match[i] = u;
return true;
}
}
}
return false;
}
int Match()
{
int ans = 0;
memset(match, -1, sizeof(match));
for (int i = 1; i <= uN; i++)
{
memset(visit, 0, sizeof(visit));
if (find(i))
ans++;
}
return ans;
}
int main()
{
scanf("%d", &T);
while (T--)
{
memset(visit, false, sizeof(visit));
memset(vec, false , sizeof(vec));
scanf("%d %d", &P, &N);
uN = P;
for (int i = 1; i <= N; i++)
{
int u, v;
scanf("%d %d", &u, &v);
v += 20;
vec[u][v] = true;
}
//读入原图
for (int i = 1; i <= P; i++)
{
for (int j = 21; j <= 20 + P; j++)
{
vec[i][j] = !vec[i][j];
}
}
//将原图取为补图
int ans = 2 * P - Match();
printf("%d\n", ans);
}
}