Is It A Tree?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16905 Accepted Submission(s): 3800
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.
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


1 #pragma comment(linker, "/STACK:1024000000,1024000000")/*栈扩展*/ 2 #include <iostream> 3 #include <string.h> 4 #include <stdio.h> 5 #include <map> 6 #include <algorithm> 7 using namespace std; 8 int ID[100112];/*ID[i]=i表示i为独立点*/ 9 int Point[100112];/*点标记*/ 10 int N_Num;/*记录出现点的个数*/ 11 int SIGN;/*记录边*/ 12 int InD[100112];/*记录每个点入度的状态*/ 13 int InD_Num;/*记录入度和*/ 14 void Cread(int N)/*初始化*/ 15 { 16 for(int i=0;i<=N;i++) 17 { 18 ID[i]=i;Point[i]=InD[i]=1; 19 } 20 return ; 21 } 22 /*int Find(int x)/寻找父亲节点,非递归 23 { 24 int tmp=x; 25 while(ID[tmp]!=tmp)tmp=ID[tmp]; 26 while(x!=tmp) 27 { 28 ID[x]=tmp; 29 x=ID[x]; 30 } 31 return tmp; 32 }*/ 33 int Find(int x)/*寻找父亲节点,递归,有时需要栈扩展*/ 34 { 35 int tmp; 36 if(ID[x]!=x)tmp=Find(ID[x]); 37 else return x; 38 ID[x]=tmp; /*路径压缩*/ 39 return tmp; 40 } 41 42 void Add(int X,int Y)/*添加点操作*/ 43 { 44 int x,y; 45 if(InD[Y])/*判断该点入度是否被标记过,记录入度和*/ 46 {InD[Y]=0;InD_Num++;} 47 x=Find(X); 48 if(Point[X]){N_Num++;Point[X]=0;} 49 y=Find(Y); 50 if(Point[Y]){N_Num++;Point[Y]=0;} 51 if(x!=y) 52 { 53 ID[x]=y; 54 SIGN++;/*记录不重复的边数*/ 55 } 56 else SIGN=1008611;/*出现回路则赋值最大值*/ 57 return ; 58 } 59 60 int main() 61 { 62 int T,N,M,i,j,k,a,b,t=1; 63 Cread(100012);SIGN=0;N_Num=0;InD_Num=0; 64 while(scanf("%d%d",&a,&b)!=EOF) 65 { 66 if(a<0&&b<0)break; 67 if(a==0&&b==0) 68 { 69 Cread(100012); 70 printf("Case %d is ",t++); 71 // printf("\t%d %d %d\n",N_Num,SIGN,InD_Num); 72 if((InD_Num==SIGN)&&(SIGN==N_Num-1||N_Num==0)) 73 printf("a tree.\n"); 74 else 75 printf("not a tree.\n"); 76 SIGN=0;N_Num=0;InD_Num=0; 77 continue; 78 } 79 Add(a,b); 80 } 81 return 0; 82 }
其实,并查集的入度的情况也是把他转换为出度处理,因为入度的情况表示的是箭头所指的方向为子节点,不过并查集每一个点顶多表示一个方向,其实也都是转为反方向处理,既转换为出度处理了的。
PS:(后来想了下,其实对并查集来说没关系,只是比较好理解而已)
参考:小希的迷宫(无向图+无回路):http://www.cnblogs.com/LWF5201314614/articles/3750343.html
更新:2015.7.30(水水更健康~,不小心把中间结果输出了,不然就1A了的)


1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 #define Max 100100 5 int ID[Max]; 6 int InD[Max]; 7 int Out_Num; 8 int Pio[Max]; 9 int SIGN; 10 int P_Num; 11 void Cread(int N) 12 { 13 for(int i=0;i<=N;i++){ID[i]=i;Pio[i]=1;InD[i]=1;} 14 } 15 int Find(int x) 16 { 17 int TMD=x,TMP; 18 while(TMD!=ID[TMD])TMD=ID[TMD]; 19 while(x!=TMD) 20 { 21 TMP=ID[x]; 22 ID[x]=TMD; 23 x=TMP; 24 } 25 return x; 26 } 27 void Update(int a,int b) 28 { 29 if(Pio[a]){P_Num++;Pio[a]=0;} 30 if(Pio[b]){P_Num++;Pio[b]=0;} 31 if(InD[b]){Out_Num++;InD[b]=0;} 32 int A=Find(a); 33 int B=Find(b); 34 if(A!=B) 35 { 36 ID[A]=B; 37 SIGN++; 38 } 39 else SIGN=Max; 40 } 41 int main() 42 { 43 int T,N,M,i,j,a,b,t=1; 44 Cread(Max);SIGN=0;P_Num=0;Out_Num=0; 45 while(scanf("%d%d",&a,&b)!=EOF) 46 { 47 if(a<0&&b<0)break; 48 if(a==0&&b==0) 49 { 50 // printf("%d %d %d\n",SIGN,Out_Num,P_Num); 51 if((SIGN==P_Num-1||P_Num==0)&&Out_Num==SIGN) 52 printf("Case %d is a tree.\n",t++); 53 else 54 printf("Case %d is not a tree.\n",t++); 55 Cread(Max);SIGN=0;P_Num=0;Out_Num=0; 56 continue; 57 } 58 Update(a,b); 59 } 60 return 0; 61 }
正解:(只需要根据树的定义,判断入度即可。。。)


1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 int d[100005]; 6 bool bo[100005]; 7 int bianshu=0; 8 void init(){ 9 memset(d,0,sizeof(d)); 10 memset(bo,0,sizeof(bo)); 11 bianshu=0; 12 } 13 int main(){ 14 int x,y,cas=1; 15 while(~scanf("%d%d",&x,&y)) 16 { 17 if(x==-1&&y==-1){ 18 break; 19 } 20 if(x==0&&y==0){ 21 int bobo=0; 22 int i; 23 for(i=1;i<=100000;i++){ 24 if(bo[i]&&d[i]==0){ 25 if(bobo==0) bobo=1; 26 else break; 27 }else 28 if(bo[i]&&d[i]!=1){ 29 break; 30 } 31 } 32 if(i<=100000) printf("Case %d is not a tree.\n",cas++); 33 else printf("Case %d is a tree.\n",cas++); 34 init(); 35 continue; 36 } 37 d[y]++; 38 bo[x]=true; 39 bo[y]=true; 40 bianshu++; 41 } 42 return 0; 43 }