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