>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;
}