P3104 [USACO14MAR]Counting Friends G(图的判定&贪心)

枚举错误的数。

因为是无向图,所以度数之和是偶数。

所以个数的和 和 枚举的数的 奇偶性必须相同。

然后就是根据每个点的度数来判定 是否能构成无向图。

采用贪心的思想,每次对度数进行排序。将第一个与后面的每个的点进行抵消。

如果遍历完度数还不能为0说明无解,否则更新再排序继续上过程。

因为减度数之后 可以看出两个有序 的序列,因此采用归并排序,时间复杂度降至

总时间复杂度:

参考代码

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n, a[502], b[500],c[500],sum=0;
scanf("%d", &n);
for (int i = 1; i <= n + 1; i++)
{
scanf("%d", &a[i]);
sum += a[i];
}
int num = 0, res[501];
for (int i = 1; i <= n + 1; i++)
{
if (sum % 2 != a[i] % 2)
continue;
int index = 0;
for (int j = 1; j <= n + 1; j++)
if (j != i)
b[index++] = a[j];
sort(b, b + n, [](const int x, const int y) {
return x > y;
});
bool flag = 1;
for (int j = 1; j <= n; j++)
{
if (b[0] == 0)
break;
int in = 1;
while (b[0] > 0 && b[in] > 0)
{
b[0]--;
b[in++]--;
}
if (b[0] > 0)
{
flag = 0;
break;
}
int p = 1, q = in, cnt = 0;
while (p < in && q < n)
if (b[p] > b[q])
c[cnt++] = b[p++];
else
c[cnt++] = b[q++];
while (p < in)
c[cnt++] = b[p++];
while (q < n)
c[cnt++] = b[q++];
for (int k = 0; k < n - 1; k++)
b[k] = c[k];
b[n - 1] = 0;
}
if (flag)
res[num++] = i;
}
printf("%d\n", num);
for (int i = 0; i < num; i++)
printf("%d\n", res[i]);
return 0;
}