Is It A Tree?

来源:互联网 发布:张国立 小鲜肉 知乎 编辑:程序博客网 时间:2024/06/06 00:27

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 1000int 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 100int 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;  }