完全多部图大致意思:输入T组数据,每组N个节点,在这N个节点上有M条无向边,将这些节点分为若干个集合,使每个集合内任意两点都是没有连接的,任意两个集合的任意两点都是有连接的,这样的图称为完全多部图。
例:
输入:
2
5 7
1 3
1 4
2 3
2 4
4 3
3 4
4 5
4 3
1 3
2 4
3 4
输出:
No
No
上述数据跟京东原题不一致,记得不是很清楚,意思都一样
本人解题思路:
先用一个set集合数组保存N+1个set,每个set都先初始化内部存1。。。N个节点。
当输入一条边的两个点a,b时,就s[a].erase(b); s[b].erase(a);注意是无向边。
利用另外一个集合sBian保存输入的边,比如输入1 3,则sBian[1]里面插入一个元素3,因为是无向边,所以sBian[3]里面也插入元素1。即:sBian[a].insert(b);sBian[b].insert(a);
这样的话就保证了每个集合的内部任意两点都无连接。最后就是判断任意两个集合的任意两点有没有连接,我用的循环,大致意思是先从s[1]中抽取第一个元素,逐渐与s[1..N+1]中的每一个元素做比较,然后在s[2]….
代码:
#include <iostream>
#include <set>
using namespace std;
int main()
{
int T = 0;
int tmp = 0;
cin >> T;
int tmp2 = T;
string *result = new string[T];
while (T--)
{
bool flg = false;//标记 true找到 false没有找到
int N, M;
set<int> *s;
set<int> *sBian;
cin >> N >> M;
s = new set<int>[N+1];
sBian = new set<int>[N+1];
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
s[i].insert(j);
}
}
for (int i = 0; i < M; i++)
{
int a, b;
cin >> a >> b;
s[a].erase(b);
s[b].erase(a);
sBian[a].insert(b);
sBian[b].insert(a);
}
//遍历所有集合查找任意两个集合里是否都有边
for (int i = 1; i <= N; i++)
{
for (set<int>::iterator it = s[i].begin(); it != s[i].end(); it++)
{
for (int j = 1; j <= N; j++)
{
if (i == j) continue;
for (set<int>::iterator it1 = s[j].begin(); it1 != s[j].end(); it1++)
{
//查找存储的sBian边
if (s[i].find(*it1) == s[i].end())
{
if (sBian[*it].find(*it1) == sBian[*it].end())
{
flg = true;//任意两个集合里没有找到边,输出NO,设置标记量
goto RESULT;
}
}
}
}
}
}
RESULT:
if (flg)
result[tmp++] = "No";
else
result[tmp++] = "Yes";
delete[] s;
delete[] sBian;
}
for (int i = 0; i < tmp2; i++)
{
cout << result[i] << endl;
}
delete[] result;
system("pause");
return 0;
}
运行截图: