Is It A Tree?(并查集)(dfs也可以解决)
Description
There is exactly one node, called the root, to which no directed edges point.
Every node except the root has exactly one edge pointing to it.
There is a unique sequence of directed edges from the root to each node.
For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are trees, but the last is not.
In this problem you will be given several descriptions of collections of nodes connected by directed edges. For each of these you are to determine if the collection satisfies the definition of a tree or not.
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. 题意:给定一定关系,判断其是否是一棵树,注意,空树也是一棵树,不能有成环的情况,不能是森林,不能有入度为2的节点。
下面给出两种思路:
1,并查集:维护一个森林 每输入一组关系(边)的时候,将这两个点连起来看做一棵树,如果可以将其合并到其他的树上的话就将其合并,并且树的总数目加1;
(注意: 只有当第二个端点值在其他树上是根节点的时候才能合并仍保持是一棵树,及从第一个端点指向第二个端点的时候会保证不会出现入度为2的点)
如果不满足合并条件的时候就将定义的树的总数加1,中间过程有可能再将这两棵树连起来,所有操作完成后,统计树的个数,要是树的棵树大于1的话则所给点不能构成一棵树
注意要排除自成环的情况,和空树的情况。
2,dfs:
将所有的边用链接表的方式存起来,当按照正常的顺序扫描一遍的时候如果是一个符合条件的树的话就不会存在一个点被访问两次,即扫描的时候不会出现visit数组被标记为走过的情况
而且当以任一点为开始扫描完一遍的时候不存在没有扫描过的点,因为不存在森林。
这里同样要考虑空树的情况。
/**
---------------------------------------------------
HuHanwu
2012-7-12
并查集快速判断每次输入是破坏树的性质
时间复杂度: o(n) n为节点的个数
---------------------------------------------------
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 1000002 int p[MAXN]; //存放父亲节点 只要存在父亲节点则此节点一存在某棵树中
int find(int x){ return p[x]==x ? x :(p[x]=find(p[x]));} //查找父亲节点并 压缩路径 int main()
{
int a,b,tree_num,t=,father_a,father_b,TF; //tree_num 保存当前的树的棵数
while(~scanf("%d%d",&a,&b) && (a>=||b>=))
{
tree_num=TF=;
if(a==)
{
printf("Case %d is a tree.\n",++t);
continue;
}//空树也是一棵树
if(a==b)
TF=;//不能成环
else
{
memset(p,,sizeof(p)); //用 0 初始化所有节点的父亲节点
p[a]=p[b]=a;
}
while(~scanf("%d%d",&a,&b) && a!=)
{
if(TF== ) // 只要已经判断出该森林已经不是树
continue;
if(p[b]!=) // b节点已经存在
{
father_b=find(b);
if(b!=father_b) // b 节点不是树根就不可以连成一棵树
{
TF=;
continue;
}
else//下面都是当b 为树根的情况
{
if(p[a]!=) // a b 节点都存在则树的的棵数-1
{
p[b]=find(a);//将两棵树连起来,只有当b是父节点的时候才可以这么连
tree_num--;
}
else //a 节点不存在 而 b 节点存在
p[b]=p[a]=a;
}
}
else
{
if(p[a]==) // a b 节点都不存在则树的棵数+1
{
p[a]=p[b]=a;
tree_num++;
}
else //a 节点存在 而 b 节点不存在
p[b]=find(a);
}
}
printf("Case %d ",++t);
if(TF==)
{
printf("is not a tree.\n");
continue;
}
if(tree_num==) // 树的棵数是否为1
printf("is a tree.\n");
else
printf("is not a tree.\n");
}
return ;
}
下面给出dfs代码,其中用链表存放边
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
#define N 50005 int head[N];
struct Edge{
int v, next;
}edge[N*];
int Ecnt; void init()
{
Ecnt = ;
memset(head, -, sizeof(head));
} void add(int u, int v)
{
edge[Ecnt].v = v;
edge[Ecnt].next = head[u];
head[u] = Ecnt++;
} bool visited[N];
bool dfs(int u)
{
for(int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].v;
if(visited[v]) return false;
visited[v] = ;
int res = dfs(v);
if(res == false) return false;
}
return true;
} struct Node {
int s, t;
}node[N]; map<int, int>mp; int in[N];
int main()
{
int s, t, cas = ;
while(~scanf("%d %d", &s, &t))
{
cas++;
if(s == && t == ){
printf("Case %d is a tree.\n", cas);
continue;
}
if(s < && t < ) break;
int c = ;
node[c].s = s, node[c++].t = t;
while(~scanf("%d %d", &s, &t), s||t)
node[c].s = s, node[c++].t = t; mp.clear();
int n = ;//结点总数
for(int i = ; i < c; i++)
{
s = node[i].s, t = node[i].t;
if(mp.find(s) == mp.end()) mp[s] = n++;
if(mp.find(t) == mp.end()) mp[t] = n++;
node[i].s = mp[s];
node[i].t = mp[t];
}
init();
memset(in, , sizeof(in));
for(int i = ; i < c; i++)
{
s = node[i].s, t = node[i].t;
add(s, t);
in[t]++;
}
bool ans = true;
int root = -;
for(int i = ; i < n; i++)
{
if(in[i] == )
{
if(root == -) root = i;
else ans = false;
}
}
if(ans == false || root == -)
{
printf("Case %d is not a tree.\n", cas);
ans = false;
continue;
}
memset(visited, , sizeof(visited));
visited[root] = ;
ans = dfs(root);
if(ans == false)
{
printf("Case %d is not a tree.\n", cas);
ans = false;
continue;
}
for(int i = ; i < n; i++)
if(!visited[i])
{
printf("Case %d is not a tree.\n", cas);
ans = false;
break;
}
if(ans)printf("Case %d is a tree.\n", cas);
}
}
Is It A Tree?(并查集)(dfs也可以解决)的更多相关文章
- F2 - Spanning Tree with One Fixed Degree - 并查集+DFS
这道题还是非常有意思的,题意很简单,就是给定一个图,和图上的双向边,要求1号节点的度(连接边的条数)等于K,求这棵树的生成树. 我们首先要解决,如何让1号节点的度时为k的呢???而且求的是生成树,意思 ...
- 第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS
原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com) 题意: 要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂):若不存在 ...
- 1021.Deepest Root (并查集+DFS树的深度)
A graph which is connected and acyclic can be considered a tree. The height of the tree depends on t ...
- 树上统计treecnt(dsu on tree 并查集 正难则反)
题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...
- Codeforces_764_C. Timofey and a tree_(并查集)(dfs)
C. Timofey and a tree time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Hdu.1325.Is It A Tree?(并查集)
Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- HDU 1232 并查集/dfs
原题: http://acm.hdu.edu.cn/showproblem.php?pid=1232 我的第一道并查集题目,刚刚学会,我是照着<啊哈算法>这本书学会的,感觉非常通俗易懂,另 ...
- Is It A Tree?(并查集)
Is It A Tree? Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 26002 Accepted: 8879 De ...
- CF109 C. Lucky Tree 并查集
Petya loves lucky numbers. We all know that lucky numbers are the positive integers whose decimal re ...
随机推荐
- [知了堂学习笔记]_用JS制作《飞机大作战》游戏_第4讲(创建敌方飞机、敌方飞机发射子弹、玩家子弹击中敌方小飞机,小飞机死亡)
一.创建敌方飞机 1.思考创建思路: 创建敌方飞机思路与创建玩家飞机思路一样: (1)思考敌方飞机具备什么属性: 敌方飞机的图片.坐标.飞行速度.状态(是否被击中) 设置小飞机被击中时消失时间.飞机可 ...
- 遍历文件 创建XML对象 方法 python解析XML文件 提取坐标计存入文件
XML文件??? xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 里面的标签都是可以随心所欲的按照他的命名规则来定义的,文件名为roi.xm ...
- POI 导出导入工具类介绍
介绍: Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发人员则可以利用NPOI (POI ...
- NestedScrollingParent, NestedScrollingChild 详解
之前听同事提起过 NestedScrollingView,但是一直没有时间去了解,最近一段时间比较空,才开始去了解.先点开,看 NestedScrollingView 源码: public class ...
- 微信小程序开发之普通链接二维码
本文主要介绍扫普通链接二维码打开小程序, 详情请看官方文档https://mp.weixin.qq.com/debug/wxadoc/introduction/qrcode.html 配置普通链接二维 ...
- Netty对WebSocket的支持(五)
Netty对WebSocket的支持(五) 一.WebSocket简介 在Http1.0和Http1.1协议中,我们要实现服务端主动的发送消息到网页或者APP上,是比较困难的,尤其是现在IM(即时通信 ...
- SEO的基本概念 和 提交SITEMAP到搜索引擎
SEO的基本概念 SEO的基本概念 :我们接触的SEO主要就是做搜索引擎的优化,让搜索引擎更好地收录 我们的网站,不管是首页还是内页,都能有很好的收录和排名.那么我们经常用到的SEO的语句是什么呢?小 ...
- SourceTree管理工具的一些使用总结
一.冲突解决 在团队合作中,如果两个人同时修改一个文件 ,这个时候如果合并他人提交的代码是会产生冲突的,怎么解决? 1.先将代码提交至本地服务器 2.合并他人代码,这个时候在工作副本中会显示我们冲突的 ...
- 对RC4算法进行改写,新的加密算法RCX。
最近研究JWT算法, JWT由header.payload.signature三个部分组成,payload是非加密的,一些敏感信息能被别人非法获得,必要时候要加密. 加密算法中,RC4算法的速度可以达 ...
- JS文本框每隔4个数字加一个空格,银行卡号文本框
<input type="text" onkeypress="return (function(key,that){return (key>47&&a ...