题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272
由于数据量很大,并查集是一个很好的解决方法。在Union的时候,如果两个节点在同一个集合中,说明存在回路。在开始的时候,忘记了一点,就是整个图的连通性,仅仅去考虑是否存在回路了。贡献了一次WA
之前WA的代码:
#include添加连通性后,AC的代码:#include using namespace std; bool flag[100005], ok;; int p[100005]; void init() { ok = true; memset(flag, false, sizeof(flag)); for(int i = 0; i < 100005; i ++) p[i] = i; } int Find(int x) { int r = x; while(r != p[r]) r = p[r]; //compress path int k = x; while(k != r) { int tmp = p[k]; p[k] = r; k = tmp; } return r; } bool Union(int a, int b) { int ra = Find(a), rb = Find(b); if(ra == rb) return false; else p[ra] = rb; //union return true; } int main() { init(); int a, b; while(scanf("%d%d", &a, &b) && !(a == -1 && b == -1)) { if(!a && !b) { if(ok) printf("Yes\n"); else printf("No\n"); init(); continue; } if(Union(a, b) == false) ok = false; } return 0; }
#include#include using namespace std; bool flag[100005], ok;; int p[100005]; void init() { ok = true; memset(flag, false, sizeof(flag)); for(int i = 0; i < 100005; i ++) p[i] = i; } int Find(int x) { int r = x; while(r != p[r]) r = p[r]; //compress path int k = x; while(k != r) { int tmp = p[k]; p[k] = r; k = tmp; } return r; } bool Union(int a, int b) { int ra = Find(a), rb = Find(b); if(ra == rb) return false; else p[ra] = rb; //union return true; } int main() { init(); int a, b; while(scanf("%d%d", &a, &b) && !(a == -1 && b == -1)) { if(!a && !b) { //check connectivity for(int i = 1, components = 0; i < 100005; i ++) if(flag[i]) { if(p[i] == i) components ++; if(components > 1) ok = false; //not connected } if(ok) printf("Yes\n"); else printf("No\n"); init(); continue; } if(Union(a, b) == false) ok = false; flag[a] = flag[b] = true; } return 0; }