当前位置:编程学习 > C/C++ >>

poj 1182 食物链 并查集

这是并查集最后一题,据说也是最经典的一题。经常前面几题的训练,这题的思路很快
就能想出来了。只需要对每个节点附加一个信息表示离根节点的距离,并且距离是模3循环的。
   注意合并时候保持距离变化的正确性。而且合并有2种情况,距离相同合并和距离不同合并。
分别对应于题目描述中的1和2操作。
   关键还是FindSet里面对距离nDis数组里面的修改,前面一直写错这个,wa了好几次,还是
看队友代码才一眼发现我又把这里写错了。。。当前距离的更新还是等于当前距离加上前一个
节点的距离再模3,类似于前面几题的更新方法。
   这种将有关系的节点放在一个并查集里面,再给每个节点附加其它信息描述其它关系的做法,
确实比较有效。。。并查集是应用于不相交集合的数据结构,看来某个时候却有妙用啊。。。

   代码如下:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int MAX = 50010;
int nN, nK;
int nSets[MAX];
int nDis[MAX];

void MakeSets(int nN)
{
    for (int i = 1; i <= nN; ++i)
    {
        nSets[i] = i;
        nDis[i] = 0;
    }
}

int FindSet(int nI)
{
    if (nSets[nI] != nI)
    {
        int nPre = nSets[nI];
        nSets[nI] = FindSet(nSets[nI]);
        nDis[nI] = (nDis[nPre] + nDis[nI]) % 3;
    }
    return nSets[nI];
}

int main()
{
    int nAns = 0;
    int nOper, nX, nY;
   
    scanf("%d%d", &nN, &nK);
    MakeSets(nN);
    while (nK--)
    {
        scanf("%d%d%d", &nOper, &nX, &nY);
        if (nX > nN || nY > nN || nOper == 2 && nX == nY)
        {
            ++nAns;
        }
        else
        {
            if (nOper == 1)
            {
                int nA = FindSet(nX);
                int nB = FindSet(nY);
                if (nA == nB)
                {
                    if (nDis[nX] != nDis[nY])
                    {
                        ++nAns;
                    }
                }
                else
                {
                    nSets[nB] = nA;
                    nDis[nB] = (nDis[nX] - nDis[nY] + 3) % 3;
                }
            }
            else
            {
                int nA = FindSet(nX);
                int nB = FindSet(nY);
                if (nA == nB)
                {
                    if ((nDis[nX] + 1) % 3 != nDis[nY])
                    {
                        ++nAns;
                    }
                }
                else
                {
                    nSets[nB] = nA;
                    nDis[nB] = (nDis[nX] + 1 - nDis[nY] + 3) % 3;
                }
            }
        }
    }
    printf("%d\n", nAns);

    return 0;
}

  

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,