sicily1034

来源:互联网 发布:哪个电子狗软件好用 编辑:程序博客网 时间:2024/06/08 12:28

这道题也算是一道简单题,但是因为我太水,以至于提交了很多次才AC,先说一下题目的大概意思吧:定义了一个叫森林的有向图,有节点和节点之间的边,只有该有向图是无环和没有2条指向同一节点的边的才能叫做森林,根节点的层数为0,根节点无父节点,输入节点和边的信息,需要输出该森林的最大深度和最大宽度

我的思路是,首先接受输入,同时进行判断是否有2条指向同一节点的边,接着就判断该有向图是否有环(DFS),如果无环则继续为每个节点赋予深度(DFS),其实这两个DFS应该可以结合来简化代码的,但是我太懒了,时间也没那么多,就没简化,最后是遍历整个有向图来找到最大宽度。刚开始为什么WA是因为我忽略了几点:1. 一个节点是可以有多个儿子的;2. 有环的情况可以是自己指向自己,或者自己指向儿子不断下去最终指回自己。AC之后我看了网上大牛牛们的做法,一般都是用DFS,不过他们判断有环的方法跟我的不太一样,感觉他们的代码更加简洁!

还有一个就是做这道题过程中知道原来不能直接对vector用memset(),具体原因是vector是使用名称为“_Myproxy”、“_Mynextiter”这两个指针来寻找与之相邻的值的,在我们定义一个向量时,它便初始化一个“_Myproxy”,当使用了memset的时候,导致了vector中的“_Myproxy”丢失,虽然仍可以对其进行push_back()等其他几乎一切操作,但是这个向量缺唯独不能执行遍历这一种操作!遇到这个错误我也是醉了...不过遇到这种这么隐晦的错误我也挺感恩的,最起码知道了不是所有东西都可以随便套上memset来进行清零操作的!

题目链接:http://soj.me/1034

废话不多说,详见代码,代码来不及变美,勿喷~:

#include <iostream>#include <cstdio>#include <vector>#include <memory.h>#include <algorithm>using namespace std;struct node{int num;int depth;int parent;vector<int> sons;};//node que[110];int maxd = 0;int maxw = 0;bool findSelf( node q[], int k, int tofind ){if ( q[k].sons.empty() ){return false;}else{vector<int>::iterator it = q[k].sons.begin();for ( ; it != q[k].sons.end(); it++ ){if ( tofind == (*it) ){return true;}else{return findSelf( q, (*it), tofind );}}}}bool dfs( node q[], int j ){maxd = max( q[j].depth, maxd );if ( q[j].sons.empty() ){return true;}else{vector<int>::iterator it;for ( it = q[j].sons.begin(); it != q[j].sons.end(); it++ ){q[(*it)].depth = q[j].depth + 1;dfs( q, (*it) );}return true;}}int main(){//freopen( "1034input.txt", "r", stdin );//freopen( "1034out.txt", "w", stdout );int n;while ( cin >> n ){int m;cin >> m;if ( n == 0 ){break;}maxd = 0;maxw = 0;node que[110];//memset( que, 0, sizeof( que ) );int isValid = 1;// 初始化数组for ( int i = 1; i <= n; i++ ){que[i].num = i;que[i].depth = -1;que[i].parent = -1;}//接受边的输入int pp, ss;for ( int i = 0; i < m; i++ ){cin >> pp >> ss;//如果该儿子已经有父亲了,则不再赋值,这个也不是森林if ( que[ss].parent != -1 ){isValid = 0;}else{que[ss].parent = pp;}que[pp].sons.push_back( ss );}//判断有环的情况if ( isValid == 1 ){for ( int k = 1; k <= n; k++ ){if ( que[k].sons.empty() ){continue;}else{isValid = !( findSelf( que, k, k ) );if ( isValid == 0 ){break;}}}}if ( isValid == 1 ){//为每个节点找到其深度,先找root,再排下来bool isRoot[110];memset( isRoot, true, sizeof( isRoot ) );//找root,对每个root,深度记为0;for ( int j = 1; j <= n; j++ ){if ( que[j].parent != -1 ){isRoot[j] = false;}else{que[j].depth = 0;}}//从root开始,为每个节点赋予深度for ( int j = 1; j <= n; j++ ){int dd = 0;if ( isRoot[j] == true ){dfs( que, j );}}//找到每个深度所对应的广度int width[110];memset( width, 0, sizeof( width ) );for ( int j = 1; j <= n; j++ ){width[que[j].depth]++;}for ( int j = 0; j < n; j++ ){if ( width[j] > maxw ){maxw = width[j];}}cout << maxd << " " << maxw << endl;}else{cout << "INVALID" << endl;}}return 0;}

这道题在看算法课的ppt的时候,给的提示是使用队列和搜索,但是使用队列的话就得是BFS了,感觉会更麻烦呢!

0 0
原创粉丝点击