思路: 当图中的集合(连通子图)个数为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 int Tree[100100]; 14 15 int findRoot(int x) 16 { 17 if(Tree[x] == -1) 18 return x; 19 int tmp = findRoot(Tree[x]); 20 Tree[x] = tmp; 21 return tmp; 22 } 23 24 int main() 25 { 26 int a, b; 27 set<int> Set; // 使用Set保存图中的所有顶点编号 28 for(int i = 0; i <= 100000; ++i) 29 Tree[i] = -1; 30 31 int rimCnt = 0; 32 while(cin >> a >> b) 33 { 34 if(a == -1 && b == -1) 35 break; 36 37 if(a == 0 && b == 0) 38 { 39 if(rimCnt == 0) // 只有输入一组数据0 0的时候,应该输出Yes 40 { 41 cout << "Yes" << endl; 42 continue; 43 } 44 int Vcnt = Set.size(); // 顶点计数 45 int Scnt = 0; // 图中的连通子图(集合)个数 46 for(set<int>::iterator iter = Set.begin(); iter != Set.end(); ++iter) 47 { 48 if(Tree[*iter] == -1) 49 { 50 Scnt++; 51 } 52 } 53 54 // 当图中的集合只有一个并且总边数等于顶点数-1的时候,输出Yes 55 if(Scnt == 1 && rimCnt == Vcnt - 1) 56 { 57 cout << "Yes" << endl; 58 } 59 else 60 { 61 cout << "No" << endl; 62 } 63 64 for(int i = 0; i <= 100000; ++i) 65 Tree[i] = -1; 66 Set.clear(); // 清空集合 67 rimCnt = 0; // 边数置零 68 continue; 69 } 70 else 71 { 72 rimCnt++; // 边计数 73 Set.insert(a); 74 Set.insert(b); 75 int ra = findRoot(a); 76 int rb = findRoot(b); 77 if(ra != rb) 78 { 79 Tree[ra] = rb; 80 } 81 } 82 83 } 84 85 return 0; 86 }