1034. Forest

来源:互联网 发布:电脑微信摇一摇软件 编辑:程序博客网 时间:2024/05/16 15:34

http://soj.sysu.edu.cn/1034


用了一位数组存。这个一位数组的元素是一个结构体,包括三个元素,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;}





法二:深搜

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;bool map[110][110];int in[110];bool vis[110];int level[110];int n, m;int w, d;bool flag;void dfs(int id, int depth){     d = max(d, depth);          for (int i = 1; i <= n; i ++)     if (map[id][i])     {         level[depth + 1] ++;                  vis[i] = true;         dfs(i, depth + 1);     }}int main(){    //freopen("input.txt", "r", stdin);    //freopen("output.txt", "w", stdout);        int a, b, i;    bool flag;        while (scanf("%d%d", &n, &m), n != 0)    {        memset(map, false, sizeof(map));        memset(in, 0, sizeof(in));        memset(level, 0, sizeof(level));        memset(vis, false, sizeof(vis));                flag = false;        for (i = 1; i <= m; i ++)        {            scanf("%d%d", &a, &b);            map[a][b] = true;            in[b] ++;                        if (!vis[b])                                vis[b] = true;            else            flag = true;        }                if (flag)                              //排除存在结点的入度大于 1 的环        {            printf("INVALID\n");            continue;        }        else        {            memset(vis, false, sizeof(vis));            d = 0;            for (i = 1; i <= n ; i ++)            if (in[i] == 0)            {                level[0] ++;                vis[i] = true;                dfs(i, 0);            }                        for (i = 1; i <= n; i ++)            if (!vis[i])            break;                        if (i <= n)                       //排除所有结点入度为 1 的环            {                printf("INVALID\n");                continue;            }                        w = 0;            for (int i = 0; i <= d; i ++)            w = max(w, level[i]);                        printf("%d %d\n", d, w);        }    }    return 0;}


法三:广搜

#include <iostream>  #include <memory.h>  #include <vector>  #include <deque>  using namespace std;  int is_visited[110];  int forest[110][110];  int all_level_width[110];  int flag;  int n;  int depth, width;  vector<int> roots;  void add_root() {      int i,j;      int sum = 0;      for (i=1;i<=n;i++) {          sum = 0;          for (j=1;j<=n;j++) {              sum+=forest[j][i];          }          if (sum ==0)              roots.push_back(i);      }  }  bool BFS_tree(int root) {      deque<int> q;      q.push_back(root);      int t, i;      int d = -1;      int size;      //size = q.size();      while (!q.empty()) {          size = q.size();          d++;          all_level_width[d]+=size;          while (size--) {              t = q.front();              q.pop_front();              for (i=1;i<=n;i++) {                  if (forest[t][i]==1) {                      if (is_visited[i]==0) {                          q.push_back(i);                          is_visited[i] = 1;                      }                      else                          return false;                  }              }          }      }      if (d > depth)          depth = d;      return true;  }  int main() {      int m;      int i,x,y;      cin >> n >> m;      while (n!=0) {          memset(is_visited, 0 ,sizeof(is_visited));          memset(forest, 0, sizeof(forest));          memset(all_level_width, 0, sizeof(all_level_width));          roots.clear();          for (i=0;i<m;i++) {              cin >> x >> y;              forest[x][y] = 1;          }          depth = 0;          width = 0;          flag = 1;          for (i=1;i<=n;i++) {              if (forest[i][i]==1) {                  flag = 0;                  break;              }          }          add_root();          if (roots.size()==0)              flag = 0;          if (flag == 1) {              for (i=0;i<roots.size();i++) {                  is_visited[roots[i]]=1;                  if (BFS_tree(roots[i])==false) {                      flag = 0;                      break;                  }                                 }          }          for (i=0;i<110;i++) {              if (all_level_width[i] > width)                  width = all_level_width[i];          }      //  cout << "result:\n" << endl;          if (flag == 0)              cout << "INVALID\n";          else               cout << depth << " " << width << endl;          cin >> n >> m;      }      return 0;  }                   


0 0