POJ 1308

//11159531	c00h00g	1308	Accepted	396K	0MS	G++	2471B	2013-01-05 16:30:10
//剧搓无比的代码
//情况太多了,一开始只考虑了,节点入度大于1和是否有一个共同祖先两个因素
//看了discuss,知道了还有几种情况没考虑,第一种是:1 2 2 1 0 0,这种会形成环,会导致我的findset一直递归(Memory Limit Exceeded)
//第二种情况是,1 1 0 0,节点指向自身,也是错误的 
//还有一点比较郁闷的是,我将from,to放在全局会导致很奇怪的现象,读入的值在执行for(1001)语句后值突然改变,不知道什么原因 
#include<cstdio>
#include<cstdio>
#include<string.h>

int parent[1001];
int indegree[1001];
int visited[1001];

//有可能会产生反复递归,1-2和2->1 
int findset(int i){return parent[i]!=i?parent[i]=findset(parent[i]):i;}

int main(){
    int cases=0;
    int from,to,a,b;
    while(scanf("%d%d",&from,&to)!=EOF){
        cases++;
        //0 0也算树,无语
        if(from==0&&to==0){
            printf("Case %d is a tree.\n",cases);
            continue;
        }
        if(from==-1&&to==-1)
            break;
        if(from==to){
            while(scanf("%d%d",&a,&b)){
                if(a==0&&b==0)
                    break;
            }
            printf("Case %d is not a tree.\n",cases);
            continue;
        }
        visited[from]=visited[to]=1;
        int Max=-1;
        if(Max<from) Max=from;
        if(Max<to) Max=to;
        int i;
        for(i=0;i<=1001;i++){
            visited[i]=0;
            indegree[i]=0;
            parent[i]=i;
        }
 
        parent[to]=from;
        indegree[to]++;
        bool flag=false;
        while(scanf("%d%d",&a,&b)){
            if(a==0&&b==0)
                break;
            //查看是否有环,查看a的父亲节点中是否有b 
            int tmp=a;
            while(parent[tmp]!=tmp){
                if(parent[tmp]==b){
                    flag=true;
                    break;
                }
                tmp=parent[tmp];
            } 
            indegree[b]++;
            if(indegree[b]>1){
                flag=true;
                //break;
            }
            if(Max<a) Max=a;
            if(Max<b) Max=b;
            parent[b]=a;
            visited[a]=visited[b]=1;
        }
        if(flag){
            printf("Case %d is not a tree.\n",cases);
        }else{
            int root,time=0;
            bool flag1=false;
            for(int i=0;i<=Max;i++){
                if(visited[i]){
                    time++;
                    if(time==1)
                        root=findset(i);
                    else{
                        if(root!=findset(i)){
                            flag1=true;
                            break;
                        }
                    }
                }
            }
            if(flag1){
                printf("Case %d is not a tree.\n",cases);
            }else{
                printf("Case %d is a tree.\n",cases);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(POJ 1308)