标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 23006 | Accepted: 7898 |
Description
Input
Output
Sample Input
6 8 5 3 5 2 6 4 5 6 0 0 8 1 7 3 6 2 8 9 7 5 7 4 7 8 7 6 0 0 3 8 6 8 6 4 5 3 5 6 5 2 0 0 -1 -1
Sample Output
Case 1 is a tree. Case 2 is a tree. Case 3 is not a tree.
Source
题意:给定一些边构成的图,问是不是树。
解析:树的特征:连通且无回路。判断连通可以用并查集,直接判断所有点的祖先都是同一个点即可;判断无回路,只需要在输入的时候判断每条边的两端点不在同一集合即可。
PS:第一次忘了初始化了~~~~(>_<)~~~~ 唉,调到死!!!
AC代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <ctime> #include <stack> using namespace std; #define INF 0x7fffffff #define LL long long #define MID(a, b) a+(b-a)/2 const int maxn = 10000 + 10; int pa[maxn], rank[maxn], vis[maxn]; void init(){ for(int i=0; i<maxn; i++){ pa[i] = i; rank[i] = 0; vis[i] = 0; } } int find(int x){ return pa[x] == x ? x : pa[x] = find(pa[x]); } void unite(int x, int y){ x = find(x); y = find(y); if(pa[x] != pa[y]){ if(rank[x] < rank[y]) pa[x] = y; else{ pa[y] = x; if(rank[x] == rank[y]) rank[x] ++; } } } int main(){ #ifdef sxk freopen("in.txt", "r", stdin); #endif // sxk int u, v; int flag = 1, Case = 0; init(); //不能忘~~~~(>_<)~~~~ while(scanf("%d%d", &u, &v)!=EOF && !(u == -1 && v == -1)){ if(!u && !v){ Case ++; int foo = 0; int i, j; if(flag){ //判连通 for(i=1; i<maxn; i++) if(vis[i]){ foo = find(i); break; } for(j=1; j<maxn; j++){ if(vis[j] && find(j)!= foo){ flag = 0; break; } } } printf("Case %d %s\n", Case, flag ? "is a tree." : "is not a tree."); init(); flag = 1; continue; } vis[u] = vis[v] = 1; if(find(u) == find(v)) flag = 0; //判无回路 else unite(u, v); } return 0; }
标签:
原文地址:http://blog.csdn.net/u013446688/article/details/43342349