您的位置:首页 > 其它

Sicily 1034. Forest

2010-07-14 22:54 274 查看
看了BBS上的题目分类说要DFS,但是听了舍友的建议,发现用一位数组存貌似也比较方便,所以就用了一位数组存。这个一位数组的元素是一个结构体,包括三个元素,fa、level、in分别表示父节点下标、当前节点层数、当前节点入度数。

首先要先考虑特殊情况,这一点其实样例中已经给出了,就是当m=0的时候,森林的深度为0,而其宽度为结点个数(因为都是根节点,我本来YY m=0时只会输出0 1...结果...)。读入时更新fa和in,当in>=2时用flg记录下来,表示已经出现“two edges pointing to the same node”。接下来要判断是否有环,这里是从当前结点往前推看是否能退出其自身就是自己的祖先,如果可以自然有环,其次,若已经向上退了n的结点还没有出现结点0或者前一种情况,则说明,有环使循环陷入死循环了。判断完了非法状态,现在就要计算森林深度和宽度,根据每个结点的fa项可以比较方便的推出(邻接矩阵貌似就比较麻烦处理了,但是前面非法状态的判断会容易些),再遍历每个节点,根据其所在的层更新width[]数组(该数组记录第i层上的元素),则所求即为max(width[i]),至此解决问题。

附上代码:

]#include <iostream>
#include <cstring>
using namespace std;
struct node
{
int fa,level,in;
node()
{
fa=in=0;
level=-1;
}
};
int main()
{
int n,m;
while (cin>>n>>m && n)
{
if (m==0)//特殊情况处理
{
cout<<"0 "<<n<<endl;
continue;
}
node f[n+1];
int flg=true;
for (int i=1;i<=m;i++)//数据读入
{
int x,y;
cin>>x>>y;
f[y].fa=x;
f[y].in++;
if (f[y].in>=2) flg=false;
}
for (int i=1;i<=n;i++)//判断是否有环
{
int t=f[i].fa,k=1;
while (t!=0 && t!=i && k<=n)
{
k++;
t=f[t].fa;
}
if (t==i || k>n)
{
flg=false;
break;
}
}
if (!flg)//如果有环或者有入读为2的结点则结束
{
cout<<"INVALID"<<endl;
continue;
}
int mdep,count=0;
for (int i=1;i<=n;i++)//更新所有树的根节点的层数,即0
if (f[i].fa==0)
{
f[i].level=0;
count++;
}
mdep=0;
while (count!=n)//更新除根节点以外的结点的层数
{
mdep++;
for (int i=1;i<=n;i++)
if (f[f[i].fa].level==mdep-1)
{
f[i].level=mdep;
count++;
}
}
cout<<mdep<<" ";
int mwid=0,width[mdep+1];
memset(width,0,sizeof(width));
for (int i=1;i<=n;i++)//由结点的层数推得每层的结点数存在width[]中,则森林的宽度即为max(width[i])
{
width[f[i].level]++;
mwid=mwid<width[f[i].level]?width[f[i].level]:mwid;
}
cout<<mwid<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: