LA - 3027 - Corporative Network

题意:有N个企业,企业间要进行合作,于是需要连线,I I J表示将I连到J去,即J作为I的父结点,有一系列的询问,E  I 表示询问I到根结点的连线距离是多长,输出这个结果。

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=13&problem=1028

——>>用并查集连起来即可。主要在于,用d[i]表示从i到根结点的距离,但在初始化后第一次赋值时应为i到其父结点的距离,如果不是的话,可能会出现修改一个结点,则其所有子结点都要修改的繁琐现象。若有1-2-3-4,担心会出现查4时d[4] = d[4] + d[3]而d[3]没改为3到根的距离?不用担心,find是递归,深度优先,在执行d[4] = d[4] + d[3]前已执行为d[3] = d[2] + d[1],更先执行为d[2] = d[2] + d[1]。

#include <iostream>

using namespace std;

const int maxn = 20000 + 10;        //企业数5 <= N <= 20000

int d[maxn], fa[maxn];      //d[i]点i到根结点的距离(但初始化后第一次给的值是i到其父结点的距离),fa[i]为结点i的父结点

int find(int x)     //带路径压缩的查找函数
{
    if(x == fa[x]) return x;
    else
    {
        int root = find(fa[x]);
        d[x] += d[fa[x]];       //改为到根的距离,这里不需考虑是否要对1000取模
        return fa[x] = root;        //路径压缩
    }
}

int main()
{
    int T, N, i, I, J;
    cin>>T;
    while(T--)
    {
        cin>>N;
        for(i = 0; i <= N; i++)     //初始化
        {
            fa[i] = i;      //根树
            d[i] = 0;       //自己到自己(根)的距离为0
        }
        char c;
        bool ok = 1;        //是否退出的标记
        while(ok && cin>>c)
        {
            switch(c)
            {
                case 'O':
                    {
                        ok = 0;
                        break;
                    }
                case 'I':
                    {
                        cin>>I>>J;
                        fa[I] = J;
                        int ans = I > J ? (I-J) : (J-I);
                        d[I] = ans % 1000;      //赋该点到其父结点的距离值
                        break;
                    }
                case 'E':
                    {
                        cin>>I;
                        find(I);        //find会维护(将d[I]改为该点到根的距离)该点到根的距离
                        cout<<d[I]<<endl;
                        break;
                    }
            }
        }
    }
    return 0;
}



posted @ 2013-01-04 21:18  xiaodanding  阅读(134)  评论(0编辑  收藏  举报