Is It A Tree?

Is It A Tree?

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 25595 Accepted Submission(s): 5842

Problem Description
A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties.
There is exactly one node, called the root, to which no directed edges point.

Every node except the root has exactly one edge pointing to it.

There is a unique sequence of directed edges from the root to each node.

For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are trees, but the last is not.

In this problem you will be given several descriptions of collections of nodes connected by directed edges. For each of these you are to determine if the collection satisfies the definition of a tree or not.

Input
The input will consist of a sequence of descriptions (test cases) followed by a pair of negative integers. Each test case will consist of a sequence of edge descriptions followed by a pair of zeroes Each edge description will consist of a pair of integers; the first integer identifies the node from which the edge begins, and the second integer identifies the node to which the edge is directed. Node numbers will always be greater than zero.

Output
For each test case display the line Case k is a tree." or the lineCase k is not a tree.”, where k corresponds to the test case number (they are sequentially numbered starting with 1).

Sample Input
6 8 5 3 5 2 6 4
5 6 0 0
8 1 7 3 6 2 8 9 7 5
7 4 7 8 7 6 0 0
3 8 6 8 6 4
5 3 5 6 5 2 0 0
-1 -1

Sample Output
Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.

Source
North Central North America 1997

Recommend
Ignatius.L | We have carefully selected several similar problems for you: 1233 1102 1875 1863 1879

这是AC的代码,换了一种思路,之前的思路我觉得也可以,但是一直是OLE,不知道那个不必要的输出是怎么来的?????

下面的代码,参考前辈的,但是自己还是不太知道,到底哪里有问题…………

WA(OLE):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 1000
int pre[MAXN] = {0};//将pre清零,如果有节点,则再赋值
int find(int a)//寻找根节点并返回
{
    if(a==pre[a])
        return pre[a];
    else
        return find(pre[a]);
}
void merge(int a, int b)//合并
{
    int p = find(a);
    int q = find(b);
    if(p!=q)
    {
     pre[q] = p;
    }
}
int main()
{
        int  a, b, t = 1;
        while(scanf("%d %d", &a, &b)!=EOF)
        {
            int flag = 0;
            int sum = 0;
            if(a==-1&&b==-1)//直接结束程序
            {
                break;
            }
            if(a!=0&&b!=0)
            {
            if(pre[a]==0)//a存在,赋值
                pre[a] = a;
            if(pre[b]==0)//b存在,赋值
                pre[b] = b;
            if(find(a)==find(b))//根节点已经相等,再次添加,就会有多条路径,不符合要求,标记
                flag = 1;
            if(!flag)//如果之前都符合要求,合并
                merge(a, b);
            while(~scanf("%d %d", &a, &b))
            {
                if(a==0&&b==0)
                break;
                if(pre[a]==0)//a存在,赋值
                pre[a] = a;
            if(pre[b]==0)//b存在,赋值
                pre[b] = b;
            if(find(a)==find(b))//根节点已经相等,再次添加,就会有多条路径,不符合要求,标记
                flag = 1;
            if(!flag)//如果之前都符合要求,合并
                merge(a, b);
            }
        for(int i=1;i<=MAXN;i++)
        {
            if(pre[i]==i)
                sum++;
            pre[i] = 0;
        }
            }
            else
                sum  = 1;
        if(sum>1||flag==1)//不符合要求,或者,根节点多于1,不是树
        {
            printf("Case %d is not a tree.\n", t);
        }
        else
            printf("Case %d is a tree.\n", t);
        t++;
        }
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 100
int pre[MAXN];//将pre清零,如果有节点,则再赋值
int book[MAXN] = {0};
int k[MAXN];
int find(int a)//寻找根节点并返回
{
    if(a==pre[a])
        return pre[a];
    else
        return find(pre[a]);
}
void merge(int a, int b)//合并
{
    int p = find(a);
    int q = find(b);
    if(p!=q)
    {
     pre[q] = p;
    }
    k[p]+=k[q];
}
int main()
{
        int  a, b, n, m, t = 1;
        while(scanf("%d %d", &a, &b)!=EOF)
        {
            int flag = 0;
            if(a==-1&&b==-1)
                break;
            for(int i=0;i<MAXN;i++)
                {
                    pre[i] = i;
                    k[i] = 1;
                }
            memset(book, 0, sizeof(book));
            if(a==0&&b==0)
                flag = 1;
            else
            {
                book[a] = 1;
                book[b] = 1;
                while(~scanf("%d %d", &n, &m))
                {
                    if(n==0&&m==0)
                        break;
                    if(find(n)!=find(m))
                        {
                            merge(n, m);
                            book[n] = 1;
                            book[m] = 1;
                        }
                    else
                        flag = 2;
                }
            }
            int sum = 0, num = 0;
            for(int i=1;i<MAXN;i++)
            {
                if(book[i]==1)
                    num++;
                if(book[i]==1&&pre[i]==i&&sum<k[i])
                    sum = k[i];
            }
            if(flag==1||(flag==0&&sum==num-1))
                printf("Case %d is a tree.\n", t++);
            else
                printf("Case %d is not a tree.\n", t++);
        }

    return 0;
}

AC

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<set>
using namespace std;
const int N=100010;
int per[N],ran[N];
void init(int n)
{
    for(int i=0;i<=n;i++)
    {
        per[i]=i;
        ran[i]=0;
    }
}

int find(int x)
{
    if(per[x]==x) 
    return x;
    return per[x]=find(per[x]);
}
set<int>s;
void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y) return ;
    if(ran[x]<ran[y]) 
    per[x]=y;
    else
    {
        per[y]=x;
          ran[x]++;
    }
}
bool same(int x,int y)
{
    return find(x)==find(y); 
}
int n,m;

int main()
{
    int k=1;
    s.clear();
    init(100000);
    int f=0;
    while(scanf("%d%d",&n,&m),n>=0||m>=0)
    {
        if(n==0&&m==0 )
        {
            if(!f)
            {
                int d=0;
                for(set<int>::iterator it=s.begin(); it!=s.end(); it++)
                {
                    if(par[*it]==*it) d++;
                }
                if(d>1 ) f=1;
            }
            if(f)
                printf("Case %d is not a tree.\n",k++);
            else
                printf("Case %d is a tree.\n",k++);

                s.clear();
                init(100000);
                f=0;
                continue;
        }
        else if(!f)
        {
            s.insert(n);
            s.insert(m);
            int ax=find(n);
            int ay=find(m);
            if(ax==ay)
            {
                f=1;
            }
            else if(m!=find(m))
            {
                f=1;
            }
            else
            {
                per[ay]=ax;
            }
        }
    }

    return 0;
}
#include <iostream>  
using namespace std;  

int pre[100005];  
bool mark[100005];  
int find (int a)  
{  
    while (a != pre[a])  
        a = pre[a];  
    return a;  
}  

int main()  
{  
    bool flag;  
    int a, b, i, k = 1, branch, node, A, B;  
    while (scanf ("%d%d", &a, &b) != EOF)  
    {  
        if (a < 0 && b < 0)  
            break;  
        if (!a && !b)  
        {  
            printf ("Case %d is a tree.\n", k++);  
            continue;  
        }  
        for (i = 1; i <= 100000; i++)  
            pre[i] = i, mark[i] = false;  
        branch = node = 0, flag = true;  
        while (a > 0)  
        {        //自己不可指向自己
            if (flag && (a == b || pre[b] != b))  
                flag = false;    
            if (flag)    //判断是否有回路  
            {  
                A = find (a);    //寻找终极父节点  
                B = find (b);  
                if (A == B)//并查集的知识,本来已经属于同一集合,现在又合并,说明有回路  
                    flag = false;  
            }  
            if (flag)  
            {  
                pre[b] = a;    //有向图合并节点  
                if (!mark[a])  
                    node++;    //累计节点数  
                if (!mark[b])  
                    node++;  
                mark[a] = mark[b] = true; //标记节点  
                branch++;    //累计树枝数  
            }  
            scanf ("%d%d", &a, &b);  
        }  
        if (flag && branch == node - 1)    //树枝数==节点数-1  
            printf ("Case %d is a tree.\n", k++);  
        else printf ("Case %d is not a tree.\n", k++);  
    }  
    return 0;  
}  
下面是用C语言实现的代码,判断一棵二叉树是否为完全二叉树。 ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; typedef struct Queue { TreeNode **data; int front; int rear; int size; } Queue; Queue *createQueue(int size) { Queue *q = (Queue *)malloc(sizeof(Queue)); q->data = (TreeNode **)malloc(sizeof(TreeNode *) * size); q->front = q->rear = 0; q->size = size; return q; } bool isEmpty(Queue *q) { return q->front == q->rear; } bool isFull(Queue *q) { return (q->rear + 1) % q->size == q->front; } void enqueue(Queue *q, TreeNode *node) { if (isFull(q)) { return; } q->data[q->rear] = node; q->rear = (q->rear + 1) % q->size; } TreeNode *dequeue(Queue *q) { if (isEmpty(q)) { return NULL; } TreeNode *node = q->data[q->front]; q->front = (q->front + 1) % q->size; return node; } bool isCompleteTree(TreeNode* root) { if (root == NULL) { return true; } Queue *q = createQueue(1000); bool flag = false; enqueue(q, root); while (!isEmpty(q)) { TreeNode *node = dequeue(q); if (node->left) { if (flag) { return false; } enqueue(q, node->left); } else { flag = true; } if (node->right) { if (flag) { return false; } enqueue(q, node->right); } else { flag = true; } } return true; } int main() { TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode)); root->val = 1; root->left = (TreeNode *)malloc(sizeof(TreeNode)); root->left->val = 2; root->right = (TreeNode *)malloc(sizeof(TreeNode)); root->right->val = 3; root->left->left = (TreeNode *)malloc(sizeof(TreeNode)); root->left->left->val = 4; root->left->right = (TreeNode *)malloc(sizeof(TreeNode)); root->left->right->val = 5; root->right->left = (TreeNode *)malloc(sizeof(TreeNode)); root->right->left->val = 6; printf("%s\n", isCompleteTree(root) ? "true" : "false"); return 0; } ``` 代码中使用了队列来存储二叉树中的节点,判断是否为完全二叉树的方法是,从根节点开始,每层的节点必须都存在,否则后面的节点都必须是叶子节点才满足完全二叉树的定义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值