46 最大团(二分图匹配)

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 gi meaning 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 N denoting 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, gi describing 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

最大团 : 一个图的最大子图(完全图);

最大团 = 补图的最大独立集 = n - 补图的最大匹配*2+补图的最大匹配 = n - 补图的最大匹配;

为什么会是这样呢,就像是下面的图一样

有6个点1 , 2 , 3 , 4  , 5 , 6;

三条边  1   2 , 1   3  ,  2  3

显然这个图的最大团是 3

首先我们将有边的删掉,没边的加上,那么除了这三条边外就全都有了;

那么我们在匹配补图的时候,1 , 2, 3, 是不可能在一块的其他的呢,就都有边了,随便匹配

{1,,,},{2,,,,},{3,,,,};

那么他的补图的最大匹配就是3,所以补图的最大独立集就是n-3=3;

最小点覆盖=最大匹配;

最小边覆盖=最大独立集=点数-最大匹配*2+最大匹配=点数-最大匹配;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Max = 55;
bool ma1[Max][Max];
int y[Max],used[Max];
vector<int> ma[Max];
int found(int x){
   int len=ma[x].size();
   for(int i=0;i<len;i++){
    int to=ma[x][i];
    if(!used[to]){
        used[to]=1;
        if(y[to]==-1||found(y[to])){
            y[to]=x;
            return 1;
        }
    }
   }
   return 0;
}
int main(){
   int t;
   scanf("%d",&t);
   while(t--){
    int n,m;
    memset(y,-1,sizeof(y));
    scanf("%d %d",&n,&m);
   for(int i=1;i<=n*2;i++){
        ma[i].clear();
    for(int j=1;j<=n*2;j++){
        if(i==j) continue;
        ma1[i][j]=false;
    }
   }
   for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
        if(i==j)continue;
        ma1[i][j]=true;
    }
   }
   for(int i=n+1;i<=n*2;i++){
    for(int j=n+1;j<=n*2;j++){
        if(i==j) continue;
        ma1[i][j]=true;
    }
   }
   for(int i=0;i<m;i++){
    int u,v;
    scanf("%d %d",&u,&v);
    ma1[u][v+n]=true;
    ma1[v+n][u]=true;
   }
   for(int i=1;i<=n*2;i++){
    for(int j=1;j<=n*2;j++){
        if(i==j) continue;
        if(ma1[i][j]==false) {
                ma[i].push_back(j);
                ma[j].push_back(i);
        }
    }
   }
   int sum=0;
   for(int i=1;i<=n*2;i++){
    memset(used,0,sizeof(used));
    sum+=found(i);
   }
   sum/=2;
   printf("%d\n",2*n-sum);
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39792342/article/details/83110316
46
今日推荐