poj1308 并查集

题意:和hdu1272差不多,只不过给出的是有向图,问图中的点是否是一颗树。

还是用并查集合并点,对于一条边,如果连接的两点已经在同一并查集内,则可以直接判否。合并时按边的方向记录点的入度,如果某个点入度大于1也就是某个点有多个父亲节点,则说明不是树。合并时顺便记录合并总次数,最后合并 点数-1 次则是树。

 1 #include<stdio.h>
 2 #include<string.h>
 3
 4 int fa[100005],num[100005];
 5 bool vi[100005];
 6
 7 void init(){
 8     for(int i=1;i<=100004;i++)fa[i]=i;
 9 }
10
11 int find(int x){
12     int r=x,t;
13     while(r!=fa[r])r=fa[r];
14     while(x!=r){
15         t=fa[x];
16         fa[x]=r;
17         x=t;
18     }
19     return r;
20 }
21
22 int main(){
23     int a,b,c=0;
24     while(scanf("%d%d",&a,&b)!=EOF&&a!=-1||b!=-1){
25         printf("Case %d is ",++c);
26         if(a==0&&b==0){printf("a tree.\n");continue;}
27         init();
28         memset(num,0,sizeof(num));
29         memset(vi,0,sizeof(vi));
30         bool f=1;
31         int x=find(a),y=find(b),cnt=0,ans=0;
32         if(!vi[a]){
33             cnt++;
34             vi[a]=1;
35         }
36         if(!vi[b]){
37             cnt++;
38             vi[b]=1;
39         }
40         num[b]++;
41         if(num[b]>1)f=0;
42         if(x!=y){
43             fa[x]=y;
44             ans++;
45         }
46         else f=0;
47         while(scanf("%d%d",&a,&b)&&a!=0||b!=0){
48             x=find(a),y=find(b);
49             if(!vi[a]){
50                 cnt++;
51                 vi[a]=1;
52             }
53             if(!vi[b]){
54                 cnt++;
55                 vi[b]=1;
56             }
57             num[b]++;
58             if(num[b]>1)f=0;
59             if(x!=y){
60                 fa[x]=y;
61                 ans++;
62             }
63             else f=0;
64         }
65         if(ans==cnt-1&&f)printf("a tree.\n");
66         else printf("not a tree.\n");
67     }
68     return 0;
69 }

时间: 2024-10-24 12:48:32

poj1308 并查集的相关文章

HDU1325 &amp;&amp;poj1308 基础并查集

和上一道小希的迷宫差不多,但是在HDU上提交一直WA,POJ过了 HDU的数据太强了吧,强的我感觉数据有问题 题意:输入若干对点,判断是否是一颗树,转化过来也就是是否存在环 点数-边数=1,还要判断每个点的入度都<=1 POJ AC代码 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> const

poj1308(并查集)

题目链接:http://poj.org/problem;jsessionid=436A34AE4BE856FB2DF9B264DCA9AA4E?id=1308 题意:给定一些边让你判断是否构成数. 思路:这道题细节很多,wa了好久.利用并查集将一棵树的节点并在一块,如果当前的边的两个端点祖先相同,则不能够成树(有环),利用num数组记录每个结点的入度,入度不能大于1.输入为 0 0表示空树,满足条件.可能出现森林,所以用vector记录出现的结点编号,最后判断所有结点是否有相同的祖先.还有不能存

POJ-1308 Is It A Tree?(并查集判断是否是树)

http://poj.org/problem?id=1308 Description A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties.There is exactl

CodeForces 745C Hongcow Builds A Nation 并查集

题意: 给了你n个城市 m条边 k个政府 每个政府管辖的区域内不能和其他政府的区域有相连 即政府之间不存在路径 问你在维护这种关系的同时 最多再加多少条边 思路: 先找出来每个联通块 再找出来没有归属的孤立的点 把他们都放到最大的联通块里 然后每个联通块之间的点两两连边是n*(n-1)/2条边 最后算出来的ans-m就好了 (看别人的博客学了一个max_element 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a

并查集(个人模版)

并查集: 1 int find(int a) 2 { 3 int r=a; 4 while(f[r]!=r) 5 r=f[r]; 6 int i=a; 7 int j; 8 while(i!=r) 9 { 10 j=f[i]; 11 f[i]=r; 12 i=j; 13 } 14 return r; 15 } 16 int merge(int a,int b) 17 { 18 int A,B; 19 A=find(a); 20 B=find(b); 21 if(A!=B) 22 { 23 f[B

并查集应用

题目描述: One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls

【bzoj3674】 可持久化并查集加强版

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 (题目链接) 题意 维护并查集3个操作:合并:回到完成第k个操作后的状态:查询. Solution 其实就是用主席树的叶子节点维护并查集的可持久化数组fa[]. 细节 终于认识到了按秩合并的强大,单纯写个路径压缩Re飞,写了路径压缩+按秩合并比单纯的按秩合并每快多少→_→ 代码 // bzoj3674 #include<algorithm> #include<iostream>

BZOJ1015[JSOI2008]星球大战starwar[并查集]

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5253  Solved: 2395[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重

HDU 5606 tree 并查集

tree 把每条边权是1的边断开,发现每个点离他最近的点个数就是他所在的连通块大小. 开一个并查集,每次读到边权是0的边就合并.最后Ans?i??=size[findset(i)],size表示每个并查集根的size Ans_i=size[findset(i)],sizeAns?i??=size[findset(i)],size表示每个并查集根的sizesize. #include<cstdio> #include<cstring> #include<algorithm>