对二分图的每个联通块进行黑白染色(孤立点不进行染色),黑为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;
}