Sicily---1034. Forest

来源:互联网 发布:网络监控调试方案 编辑:程序博客网 时间:2024/05/29 13:15

并查集在有向图中的应用

题目:
Description
In the field of computer science, forest is important and deeply researched , it is a model for many data structures . Now it’s your job here to calculate the depth and width of given forests.
Precisely, a forest here is a directed graph with neither loop nor two edges pointing to the same node. Nodes with no edge pointing to are roots, we define that roots are at level 0 . If there’s an edge points from node A to node B , then node B is called a child of node A , and we define that B is at level (k+1) if and only if A is at level k .
We define the depth of a forest is the maximum level number of all the nodes , the width of a forest is the maximum number of nodes at the same level.
Input
There’re several test cases. For each case, in the first line there are two integer numbers n and m (1≤n≤100, 0≤m≤100, m≤n*n) indicating the number of nodes and edges respectively , then m lines followed , for each line of these m lines there are two integer numbers a and b (1≤a,b≤n)indicating there’s an edge pointing from a to b. Nodes are represented by numbers between 1 and n .n=0 indicates end of input.
Output
For each case output one line of answer , if it’s not a forest , i.e. there’s at least one loop or two edges pointing to the same node, output “INVALID”(without quotation mark), otherwise output the depth and width of the forest, separated by a white space.

思路:由于题目要求合法的图应该 ①没有环 ②没有入度大于1的顶点——符合树的特点,因此,其实合法的输入其实是一堆树的集合,即为森林 (o(╯□╰)o 好吧,这点从题目名称就能看得出来)

解决方法:①判断是否会生成环最有效的方法是并查集 ②判断入度是否会大于一则可以简单的看要指向的结点是否有父节点

代码如下:

#include<stack>#include<iostream>#include<cmath>#include<string>#include<cstdio>#include<algorithm>#include<sstream>#include<iomanip>#include <cstring>#include <cstdlib>#include <vector>#include <map>#include <queue>#include <set>using namespace std;int father[110];//直接的父亲,例如 3→2→4 则father[4] == 2  而 father[2] == 3;                //根的父亲定义为 0 int se_father[110];//用于并查集,存储的是所在树的根,                    //例如 3→2→4 则se_father[4] == 3 , se_father[2] == 3;int level[110];// i 在第level[i]层,定义根所在层为第一层int get_se_fa(int ch)//获取ch所在树的根,ch孤单一人的话则返回ch本身{    int fa = se_father[ch];    if (fa == 0)        return ch;    else return se_father[ch] = get_se_fa(fa);            //这里是se_father[ch] = get_se_fa(fa) 而非 get_se_fa(fa),即为并查集的思想}int getLevel(int a){    if (level[a] != 0)//之前已经记录过,则直接返回        return level[a];    int fa = father[a];    if (fa == 0)     //如果a是根,则标记level为1        return level[a] = 1;    else return level[a] = getLevel(fa) + 1; //否则递归计算层数}int main(){    int n, m;    while (cin >> n >> m, n)    {        memset(father, 0, sizeof(father));        memset(se_father, 0, sizeof(se_father));        memset(level, 0, sizeof(level));        int a, b;        bool INVflag = false;//标记是否已经判定为"INVALID"        for (int i = 0; i < m; i++)        {            cin >> a >> b;            if (INVflag)                continue;            //a == b表示自己指向自己; get_se_fa(b) != b表示已经有结点指向b;                //get_se_fa(a) == get_se_fa(b) 表示已经在同一树里            if (a == b || get_se_fa(b) != b || get_se_fa(a) == get_se_fa(b))            {                INVflag = true;                cout << "INVALID" << endl;                continue;/*之所以用continue而不是break是因为要把输入处理完,才能进行                            下一个test case*/            }            father[b] = a;//标记b的直接父亲为a            se_father[b] = get_se_fa(a);//将b所在树和a所在树合并,并查集思想        }        if (!INVflag)        {            int width[110] = { 0 };            int max_depth = -9999;            int max_width = -9999;            for (int i = 1; i <= n; i++)            {                int t = getLevel(i);                if (t > max_depth)   // t 是否比当前最大深度还大                    max_depth = t;                width[t]++;          //第 t 层的宽度加一            }            for (int i = 0; i < 110; i++)//循环找出最大宽度            {                if (width[i] > max_width)                    max_width = width[i];            }            cout << max_depth-1 << " " << max_width << endl;//max_depth-1 是因为我在getlevel()里面把根的深度定为 1        }    }}
0 0
原创粉丝点击