原题题面
题目描述
现在有多个数对 ,满足 。接下来给出一个有 个节点, 条边的图,保证不会有自环和重边,不保证联通,且满足 。对于每条边,你可以放置一组数对,数对的两个数对应边的两个端点。要求每个数对最多用一次( 在这里 认为是同一个数对 ),对于每个节点,其所连的所有边中朝向当前节点的数对端的数相同。
现在请你输出能放置的数对的最大数量。
输入输出格式
题目分析
这是一道 思维题,题目要求我们对每条边进行放置,每个节点所连边的相邻端数字相等。
由此,我们可以换一个切入点,我们对每个节点进行赋值,对于有相连边的节点,其相连边上可放置的数对的值便为相连节点的值,这样的话,我们便可以依次对每个边的合理性进行判断。
对于节点数小于 的图,在题目限制条件下,我们对每个节点可以赋其编号的值,显而易见,每条边上放置的数对都是合理的。
对于节点数为 的图,我们可以知道其中有两个节点所赋的值是相同的,对于这两个点 ,所有与这两个点同时相连的第三个点 ,即 与 联通, 与 联通,我们需要删掉这两条联通边的一条。经过这个操作后,剩下的数对均合理。于是,题目便成为枚举 ,统计剩下数对数量的最大值。
Accept代码
#include <bits/stdc++.h>
using namespace std;
const int N = 8;
bool g[N][N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i ++)
{
int a, b;
cin >> a >> b;
g[a][b] = g[b][a] = true;
}
if (n < 7)
{
cout << m;
return 0;
}
int res = 0;
for (int i = 1; i <= n; i ++)
for (int j = i + 1; j <= n; j ++)
{
int tem = 0;
for (int t = 1; t <= n; t ++)
{
if (t == i || t == j) continue;
if (g[i][t] && g[j][t]) tem ++;
}
res = max(res, m - tem);
}
cout << res;
return 0;
}