题意:给定一组有序点对,如(a,b)表示有边从a指向b。问这组点对是否能够形成树。
思路:如果输入有(a,b),如果b没有其他前驱而且a不为b的前驱(或者a与b相等),则合并a和b,注意合并方向。对所有出现的点进行标记,最后通过father[i] = i的个数判断是树还是森林。
#include <stdio.h> #include <string.h> #define N 105 int T=1,a,b; int father[N],num[N]; void init(){ int i; memset(num,0,sizeof(num)); for(i = 1;i<N;i++) father[i] = i; } int find(x){ if(father[x] == x) return x; return father[x] = find(father[x]); } void merge(int x,int y){ father[y] = find(x); } int main(){ freopen("a.txt","r",stdin); while(scanf("%d %d",&a,&b) && !(a==-1&&b==-1)){ int flag = 1,i,j,sum; if(!a && !b){ printf("Case %d is a tree.\n",T++); continue; } init(); do{ num[b] = num[a] = 1; if(find(a)!=find(b) && father[b] == b) merge(a,b); else flag = 0; }while(scanf("%d %d",&a,&b) &&a&&b); if(flag) for(i = 1,sum=0;flag&&i<N;i++){ if(num[i] && father[i]==i) sum++; if(sum > 1) flag=0; } if(!sum) flag = 0; if(flag) printf("Case %d is a tree.\n",T++); else printf("Case %d is not a tree.\n",T++); } return 0; }