求助,带权并查集,为什么find函数注释中的写法是错误的?
查看原帖
求助,带权并查集,为什么find函数注释中的写法是错误的?
676452
GaoKui楼主2022/12/26 21:09
#include <bits/stdc++.h>

using namespace std;

typedef struct edge // 边的结构体
{
    int from, to, anger; // 起点,终点,权值

    bool operator<(const edge &rhs) const // 用于优先队列
    {
        return anger < rhs.anger;
    }
}edge;

const int MAX_V = 20002;

int n, m;
// 大顶堆
priority_queue<edge, vector<edge>, less<edge>> edges;
int dsu[MAX_V]; // 并查集本身
int val[MAX_V]; // 并查集每个结点的权值

int find(int x) // 查找最远祖先,并路径压缩,更新权值
{
    if (dsu[x] != x)
    {
        int temp = find(dsu[x]);
        val[x] = ((val[x] + val[dsu[x]]) & 1);
        dsu[x] = temp;

        /*
        错误写法:
        val[x] = ((val[x] + val[dsu[x]]) & 1);
        dsu[x] = find(dsu[x]);
        */
    }

    return dsu[x];
}

void unite(int x, int y) // 合并,并赋予权值
{
    // x对y的关系是不在一个监狱,即1,由此推算px对py的关系
    int px = find(x);
    int py = find(y);

    dsu[px] = py; // 将px接到py下
    val[px] = ((1 + val[y] - val[x]) & 1);
}

int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t1, t2;
    edge tmp;
    cin >> n >> m;

    for (int i = 1; i <= n; i++)
    {
        dsu[i] = i; // 初始化并查集
    }

    for (int i = 0; i < m; i++)
    {
        cin >> tmp.from >> tmp.to >> tmp.anger;
        edges.push(tmp); // 在大顶堆中放入数据
    }

    while (m--)
    {
        // 首先是条件1,若遇到两个点在同一集合,才会去判断条件2
        // 条件2:如果两个点的权值相加取模是0,说明这两个点必须要在同一座监狱,不能分到两座监狱
        // 即出现了矛盾,输出当前边权即可
        if (find(edges.top().from) == find(edges.top().to) && 
            !((val[edges.top().from] + val[edges.top().to]) & 1))
        {
            cout << edges.top().anger;
            exit(0);
        }

        // 合并,权值的运算在函数中已经实现
        unite(edges.top().from, edges.top().to);
        edges.pop();
    }

    cout << '0';

    return 0;
}

能够举出什么反例吗?

2022/12/26 21:09
加载中...