Sicily 1034 Forest
来源:互联网 发布:linux ln命令 编辑:程序博客网 时间:2024/06/05 09:07
题目:http://soj.me/1034
题目大意:
给出一个森林,首先判断这个森林是否合法,然后求出这个森林的最大深度和最大宽度。
不合法的意思是:有环或者存在多个结点指向同一个结点的情况。
最大深度的定义是:所有树的深度的最大值,根结点的深度为0。
最大宽度的定义是:同一层的结点总数为该层的宽度,所有层的最大宽度为森林的最大宽度。
算法实现:
用拓扑排序的方法判断有向图是否有环,然后用dfs求出最大深度和最大宽度,同时判断是否有多个结点指向同一个结点的情况(被指向的结点会被访问多次)。
具体代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<stack>#define MAXN 101using namespace std;struct ArcNode{ int adjvex; ArcNode *next;};struct VNode{ ArcNode *first;};struct Graph{ int vexnum; VNode v[MAXN];};int max_depth;int in[MAXN],vis[MAXN],node_num[MAXN];Graph g;bool dfs(int cur,int level){ if(vis[cur]) return 0; vis[cur]=1; node_num[level]++; if(g.v[cur].first==NULL) { if(level>max_depth) max_depth=level; return 1; } ArcNode *p; for(p=g.v[cur].first;p;p=p->next) if(!dfs(p->adjvex,level+1)) return 0; return 1;}/**利用拓扑排序判断有向图是否有环*/bool topological_sort(Graph &g,int *in){ int *indegree=(int *)malloc((g.vexnum+1)*sizeof(int)); memcpy(indegree,in,(g.vexnum+1)*sizeof(int)); stack<int> s; for(int i=1;i<=g.vexnum;i++) if(indegree[i]==0) s.push(i); int cnt=0; while(!s.empty()) { int i=s.top(); s.pop(); cnt++; ArcNode *p; for(p=g.v[i].first;p;p=p->next) { int k=p->adjvex; indegree[k]--; if(indegree[k]==0) { s.push(k); } } } free(indegree); if(cnt<g.vexnum) return 0; return 1;}int main(){ int n,m; while(cin>>n>>m&&n>0) { g.vexnum=n; for(int i=1;i<=n;i++) g.v[i].first=NULL; memset(in,0,sizeof(in)); for(int i=1;i<=m;i++) { int v1,v2; cin>>v1>>v2; in[v2]++; ArcNode *tmp=new ArcNode(); tmp->adjvex=v2; tmp->next=g.v[v1].first; g.v[v1].first=tmp; } if(!topological_sort(g,in)) { cout<<"INVALID"<<endl; continue; } bool invalid=0; memset(vis,0,sizeof(vis)); max_depth=0; memset(node_num,0,sizeof(node_num)); for(int i=1;i<=n;i++) if(in[i]==0) { if(!dfs(i,0)) { invalid=1; break; } } if(invalid) { cout<<"INVALID"<<endl; continue; } int max_width=0; for(int i=0;i<MAXN;i++) if(node_num[i]>max_width) max_width=node_num[i]; cout<<max_depth<<" "<<max_width<<endl; } return 0;}
收获:用拓扑排序判断有向图是否有环的方法是判断是否所有结点都被排序,如果存在没有被排序的结点,那么就会有环。这个一个比较保险的方法。如果使用对每个结点都进行dfs,根据是否存在被重复访问的结点判断是否有环的方法,是不正确的。因为我们不知道结点的访问顺序,从而会出现孩子结点被重复访问的情况。
- Sicily 1034 Forest(DFS)
- sicily 1034(Forest)
- Sicily 1034 Forest
- Sicily 1034 Forest
- Sicily 1034. Forest
- Sicily 1034. Forest
- [sicily online]1034. Forest
- sicily 1034.Forest
- Sicily 1034. Forest
- sicily 1034. Forest
- #sicily#1004. Forest
- Sicily---1034. Forest
- sicily-1034. Forest
- 1034 forest
- Forest
- Forest
- sicily 1034
- Sicily 1034
- 详解JRE和JDK的区别
- 全排列问题
- Android Api 常用类库包介绍
- LNMP= CentOS+Nginx+MySQL+PHP 安装配置及简易建站笔记(持续更新中)
- 在C#中的使用Measurement Studio 之二 控件1
- Sicily 1034 Forest
- 液晶屏测试小程序
- Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- (转)101款web应用推荐 从思维导图到Bug跟踪(上)
- jquery 方法扩展
- 判断浏览器版本
- hdu 1102 Constructing Roads
- windows下,string 转 LPCWSTR
- 关于JVM和Java的跨平台性