小鑫的城堡
2014-08-15 20:40
183 查看
Description从前有一个国王,他叫小鑫。有一天,他想建一座城堡,于是,设计师给他设计了好多简易图纸,主要是房间的连通的图纸。小鑫希望任意两个房间有且仅有一条路径可以相通。小鑫现在把设计图给你,让你帮忙判断设计图是否符合他的想法。比如下面的例子,第一个是符合条件的,但是,第二个不符合,因为从5到4有两条路径(5-3-4和5-6-4)。 Input多组输入,每组第一行包含一个整数m(m < 100000),接下来m行,每行两个整数,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。 Output每组数据输出一行,如果该城堡符合小鑫的想法,那么输出"Yes",否则输出"No"。Sample Input
5 2 5 2 3 1 3 3 6 4 6 6 1 2 1 3 3 4 3 5 5 6 6 4Sample Output
Yes No
代码:
(此题挺难,一输入0 0时保证输出Yes。二保证不出现环,也就是每添加新元素时判断两者祖宗是否一样,若一样,合并函数返回值0,不一样,返回1,在后面控制flag。三保证只是一个集合,这一点好难写程序,下面代码中引入了一个t值,增加元素,标记一下,判断是否为新元素,如果增加n个新元素,t就变为t+n,此时如果只有一个集合,那么合并的次数也会为n,在返回值为1的情况下t--,最终t=1。如果有多个集合,t最终大于1。 为什么要这样判断集合,因为元素数不是连续的,不能用传统的找祖宗个数=1来判断,此法很好很妙,利用了键。)
#include <stdio.h>#include <string.h>int bin[100001];int wz[1000001];int find(int x){ int r = x; while (bin[r]!=r) { r=bin[r]; } int i = x; while(bin[i]!=r) { int j; j = bin[i]; bin[i] = r; i = j; } return r;}int merge(int x,int y){ int fx,fy; fx = find(x); fy = find(y); if(fx != fy) { bin[fy] = fx; return 1; } else return 0;}int main (){ int x,y,flag,i,t,T,j; while (~scanf("%d",&T)) { scanf("%d%d",&x,&y); memset(wz,0,sizeof(wz)); memset(bin,0,sizeof(bin)); for (i = 0;i < 100001;i++) { bin[i] = i; } merge(x , y); wz[x] = 1; wz[y] = 1; t = 1; (进一步解释t:可理解为键,初始连接两个,键为1,同一集合内增加n个新元素,) flag = 1; for(j = 1;j<=T-1;j++) (无论怎么连,需要n个新键,r个集合需要的新键为n-r+1个) { scanf("%d%d",&x,&y); if (wz[x] == 0) { t++; wz[x] = 1; } if (wz[y] == 0) { t++; wz[y] = 1; } int z = merge(x,y); if (z == 1) t--; else flag = 0; } if (flag == 1&&t==1) printf ("Yes\n"); else printf ("No\n"); } return 0;}