| 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