對二分圖的每個聯通塊進行黑白染色(孤立點不進行染色),黑爲1,白爲2,未染色爲0,然後統計出左右集合X,Y的數量,我們知道要兩個數乘積最大,則其差值最小,利用bitset優化,然後答案就是兩個集合內點數目乘積減去m。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
#include <bitset>
using namespace std;
int n,m,u,v;
int c[100005],L[5];
vector <int> G[100005];
void dfs(int u)
{
L[c[u]]++;
int len = G[u].size();
for(int i = 0; i < len; ++i)
{
int v = G[u][i];
if(c[v]==0)
{
c[v] = 3 - c[u];
dfs(v);
}
}
}
bitset <10005> s;
int main()
{
//freopen("in.txt","r",stdin);
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;++i)G[i].clear();
for(int i=0;i<m;++i)
{
scanf("%d%d",&u,&v);
u--;v--;
G[u].push_back(v);
G[v].push_back(u);
}
memset(c,0,sizeof(c));
s.reset();s[0]=1;
for(int i=0;i<n;++i)
{
if(!c[i])
{
memset(L,0,sizeof(L));
c[i]=1;
dfs(i);
s=s<<L[1]|s<<L[2];
}
}
int ans;
for(int i=n/2;i>=1;--i)
{
if(s[i]){ans=i;break;}
}
printf("%d\n",ans*(n-ans)-m);
}
return 0;
}