并查集主要处理集合 ,它可以快速
判断一个元素e是否属于集合S;
合并两个集合;
缺点:
删除一个元素e;
hdu1272 题目的要求有两点:
所有房间都联通;
不存在回路(环);
即 节点个数=边数+1
AC code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 import java.io.*;public class Main implements Runnable { public void solve () { int MAX = 100001 ; int [] par = new int [MAX]; boolean [] nodes = new boolean [MAX]; int p, q, lines = 0 ; boolean yes = true ; for (int i = 0 ; i < MAX; i++) par[i] = i; while ((p = nextInt()) != -1 && (q = nextInt()) != -1 ) { if (p == 0 && q == 0 ) { for (int i = 0 ; i < MAX; i++) { if (nodes[i]) lines--; } if (yes && (lines == -1 || lines == 0 )) out.println("Yes" ); else out.println("No" ); yes = true ; lines = 0 ; for (int i = 0 ; i < MAX; i++) { par[i] = i; nodes[i] = false ; } } else if (lookup(par, p) == lookup(par, q)) { yes = false ; } collect(par, p, q); nodes[p] = nodes[q] = true ; lines++; } } public void collect (int [] par, int p, int q) { int fp = lookup(par, p), fq = lookup(par, q); if (fp < fq) { par[fq] = fp; } else { par[fp] = fq; } } public int lookup (int [] par, int p) { if (par[p] == p) { return p; } else { return (par[p] = lookup(par, par[p])); } } @Override public void run () { init(); solve(); out.flush(); } public static void main (String[] args) { new Main ().run(); } StreamTokenizer in; PrintWriter out; public void init () { in = new StreamTokenizer (new BufferedReader (new InputStreamReader (System.in))); out = new PrintWriter (new OutputStreamWriter (System.out)); } public int nextInt () { try { in.nextToken(); return (int ) in.nval; } catch (IOException e) { throw new IllegalStateException (e); } } }
值得注意的是这里的数据样本,每个节点对都是唯一的,没有出现 5 2 2 5 这种情况。 如果直接是 0 0,需要输出 Yes。 这道题中的数据有点巧,没有很刁钻,所以递归可以过。假如输入的数据是 100000 99999 99999 99998 …… 3 2 2 1 1 100000 0 0 那么递归就惨了。