239. 奇偶游戏 带权并查集 种类(扩展域)并查集 两种解法

本文介绍了一种使用带权并查集解决特定关系判断问题的方法,涉及区间处理和权值转移。在AC自动机的实现中,通过判断权值关系来确定元素所属类别,并通过并查集优化合并操作。代码示例展示了如何处理边权并进行判定,最后给出了完整的AC代码实现。
摘要由CSDN通过智能技术生成

题目

在这里插入图片描述

题解思路

复习了下 (几个月没碰又忘了)
带权并查集是用来判断某些东西的一种相互关系。
边权代表与根节点的权值进而判断与其他节点的关系。
带权并查集一般都需要进行区间的处理 变成 左开右闭 ()
权值转移

            w[fx] = ( book + w[y] - w[x] + 2 ) % 2 ;
            a[fx] = fy ;

判定的话只需要用小的减大的即可。

种类(扩展域)并查集
在这里插入图片描述
将偶数关系视为同类
和就之前帮派那题差不多了。

AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <unordered_map>

using namespace std;

const  int  INF =  0x3f3f3f3f;

unordered_map <int , int  > q ;
int a[100100]  , w[100100] ;

int find2(int x)
{
	if (x != a[x])
	{
		int t = a[x];   //暂存父节点
		a[x] = find2(a[x]); //寻找根节点并且合并
		w[x] = ( w[t] + w[x] )%2 ;   //找到根节点后 不断将根节点前的点的权值累加并更新
	}    //(递归思想) 最后x和根节点相连
	return a[x]; //并且累加上了之前(从X到根节点)的权值
}


int main ()
{
    ios::sync_with_stdio(false);
    int n ,m , flag = 0  ;
    cin>>n>>m;
    n = 1 ;
    for (int i = 1 ; i <= 2*m + 1  ; i++ )
        a[i] = i;
    for (int i = 1 ; i <= m ; i++ )
    {
        string p = "";
        int t1 ,t2 , book = -1 ;
        cin >> t1 >> t2 >> p;
        if ( flag )
            continue;
        if (t1 > t2 )
            swap(t1,t2) ;
        t1-- ;
        if ( q.count(t1) == 0 )
        {
            q[t1] = n;
            n++;
        }
        if ( q.count(t2) == 0 )
        {
            q[t2] = n ;
            n++;
        }
        if ( p == "even")
            book = 0 ;
        else
            book = 1 ;
        int fx = find2(q[t1]) ;
        int fy = find2(q[t2]) ;
        int x = q[t1] ;
        int y = q[t2] ;
        if ( fx ==  fy )
        {
            if ( book != (w[x] - w[y] + 2 )%2 )
            {
                flag = i-1;
            }
        }else
        {
            w[fx] = ( book + w[y] - w[x] + 2 ) % 2 ;
            a[fx] = fy ;
        }
        if ( i == m && flag == 0 )
            flag = m;
    }
    cout<<flag<<"\n";
    return 0 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值