这是一棵树吗?【数论】

>Description
DD和QQ在玩游戏,DD在地上画了一棵树(图论中的树),然后他告诉QQ这棵树的度数序列。QQ马上说这不是一棵树。DD认为自己被QQ鄙视了,他们吵了起来。

但DD随后发现自己算错了度数序列,QQ说的是对的。DD很奇怪为什么QQ反应得这么快。

现在给出一个图的度数序列,你需要做的就是像QQ一样:判断这是否可能是一棵树的度数序列。


>Input
输入只有一行,首先给出一个整数 N,表示顶点个数,后面跟着 N 个整数,表示这个图的度数序列,每个数不超过 100。

>Output
如果输入可能是一棵树的度数序列,则输出“Possible”,否则输出“Impossible”。


>Sample Input
3 1 2 1

>Sample Output
Possible

对于 100% 的数据,有 1≤N≤100。


>解题思路
度数=入度+出度

我比赛时打的O(n)暴力,但是有一个点WA了,说明我的思想还是有一丝漏洞的==

bool cmp (int aa, int bb) {return aa > bb;}
void dfs (int now, int s)
{
	if (s == 0) return;
	int son = cnt + 1;
	cnt = son + s - 1;
	if (cnt > n)
	{
		printf ("Impossible");
		exit (0);
	}
	for (int i = son; i <= son + s - 1; i++)
	  dfs (i, a[i] - 1);
}
int main()
{
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++) scanf ("%d", &a[i]);
	sort (a + 1, a + 1 + n, cmp);
	if (n == 1 && a[1] == 0)
	{
		printf ("Possible");
		return 0;
	}
	cnt = 1;
	dfs (1, a[1]);
	printf ("Possible");
	return 0;
}

正解:O(1)
还是很简单的(为什么我打了个O(N)==)
因为一个点的度数为入度+出度,说明一条边我们计算了两次,所以 s u m ( a i ) / 2 sum(ai)/2 sum(ai)/2就是整棵树的路径数,按照一棵n个节点树有n-1条路径的性质可以直接判断


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 105
using namespace std;

int n, a[N], sum;

int main()
{
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++) scanf ("%d", &a[i]);
	for (int i = 1; i <= n; i++)
	{
		if (a[i] >= n) //有一些Impossible的数据可能总数达到了,但是单个点的度数明显不能达到
		{
			printf ("Impossible");
			exit (0);
		}
		sum += a[i];
	}
	if (sum / 2 != n - 1) printf ("Impossible");
	else printf ("Possible");
	return 0;
}

你可能感兴趣的:(数论)