传送门 思路:n个同学,有的相互认识,问能否划分两组互相不认识的同学,并求出最大的相互认识的同学对数。
先用染色法判断是否是二分图,再使用匈牙利匹配法判断最大的匹配数。
using namespace std;
vector<int>G[10005], V[10005];
int g[10005], vis[10005], g1[10005];
int n, m;
int sum;
int c1, c2;
int Link[205];
bool Find(int u)
{
for(int i = 0; i < V[u].size(); i++)
{
int v = V[u][i];
if(!vis[v])
{
vis[v] = 1;
if(Link[v] == -1 || Find(Link[v]))
{
Link[v] = u;
return true;
}
}
}
return false;
}
int solve()
{
int cnt = 0;
memset(Link, -1, sizeof(Link));
for(int i = 1; i <= n; i++)
{
if(V[i].size())
{
memset(vis, 0, sizeof(vis));
if(Find(i)) cnt++;
}
}
return cnt;
}
bool dfs(int u, int col)
{
vis[u] = col;
if(col == 0)
c1++;
else c2++;
for(int i = 0; i < G[u].size(); i++)
{
int t = G[u][i];
if(vis[t] == vis[u])
{
return false;
}
else if(vis[t] == -1)
{
if(!dfs(t, !col))
{
return false;
}
}
}
return true;
}
void init(int n)
{
memset(vis, -1, sizeof vis);
memset(g, 0, sizeof g);
memset(g1, 0, sizeof g1);
for(int i = 1; i <= n; i++)
G[i].clear();
for(int i = 1; i <= n; i++)
V[i].clear();
}
int main()
{
int T;
while(cin >> n >> m)
{
int u, v;
init(n);
for(int i = 1; i <= m; i++)
{
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
V[u].push_back(v);
g[u] = 1;
g[v] = 1;
}
int flag = 0;
int t = 0;
for(int i = 1; i <= n ; i++)
{
c1 = c2 = 0;
if(g[i] && vis[i] == -1)
{
if(!dfs(i, 0))
{
flag = 1;
break;
}
}
}
if(flag)
cout << "No" << endl;
else
{
cout << solve() << endl;
}
}
return 0;
}