小希的迷宫 HDU - 1272 (并查集)
思路: 当图中的集合(连通子图)个数为1并且边数等于顶点数-1(即改图恰好为一棵生成树)时,输出Yes.
此题的坑:(1) 如果只输入0 0算作一组数据的话答案应该输出Yes
(2) 输入数据可能并不是连通图,有可能一开始不连通,所以最后一定要判断其连通子图个数是不是1
1 #include<iostream> 2 #include<vector> 3 #include<string> 4 #include<cmath> 5 #include<set> 6 #include<algorithm> 7 #include<cstdio> 8 #include<map> 9 #include<cstring> 10 11 using namespace std; 12 13 // 小希的迷宫 HDU - 1272 14 15 /** 16 思路: 当图中的集合(连通子图)个数为1并且边数等于顶点数-1(即改图恰好为一棵生成树)时,输出Yes. 17 此题的坑:(1) 如果只输入0 0算作一组数据的话答案应该输出Yes 18 (2) 输入数据可能并不是连通图,有可能一开始不连通,所以最后一定要判断其连通子图个数是不是1 19 */ 20 21 int Tree[100100]; 22 23 int findRoot(int x) 24 { 25 if(Tree[x] == -1) 26 return x; 27 28 // 路径压缩 29 int tmp = findRoot(Tree[x]); 30 Tree[x] = tmp; 31 return tmp; 32 } 33 34 int main() 35 { 36 int a, b; 37 set<int> Set; // 使用Set保存图中的所有顶点编号 38 for(int i = 0; i <= 100000; ++i) 39 Tree[i] = -1; 40 41 int rimCnt = 0; 42 while(cin >> a >> b) 43 { 44 if(a == -1 && b == -1) 45 break; 46 47 if(a == 0 && b == 0) 48 { 49 if(rimCnt == 0) // 只有输入一组数据0 0的时候,应该输出Yes 50 { 51 cout << "Yes" << endl; 52 continue; 53 } 54 int Vcnt = Set.size(); // 顶点计数 55 int Scnt = 0; // 图中的连通子图(集合)个数 56 for(set<int>::iterator iter = Set.begin(); iter != Set.end(); ++iter) 57 { 58 if(Tree[*iter] == -1) 59 { 60 Scnt++; 61 } 62 } 63 64 // 当图中的集合只有一个并且总边数等于顶点数-1的时候,输出Yes 65 if(Scnt == 1 && rimCnt == Vcnt - 1) 66 { 67 cout << "Yes" << endl; 68 } 69 else 70 { 71 cout << "No" << endl; 72 } 73 74 for(int i = 0; i <= 100000; ++i) 75 Tree[i] = -1; 76 Set.clear(); // 清空集合 77 rimCnt = 0; // 边数置零 78 continue; 79 } 80 else 81 { 82 rimCnt++; // 边计数 83 Set.insert(a); 84 Set.insert(b); 85 int ra = findRoot(a); 86 int rb = findRoot(b); 87 if(ra != rb) 88 { 89 Tree[ra] = rb; 90 } 91 } 92 93 } 94 95 return 0; 96 }