思路:
关于本文中首次用到的一些STL函数,详见: FORMER_BLOG 。种类并查集+离散化 这应该是一种非常简便的离散化方法:
因为数字的范围太大(1e9),不得不离散化,即将 5000*2 个 index 通过映射 存起来。 把每个询问存进结构体,数组和队列皆可;把全部的端点 index 存进 f 数组 (par 和 val 的 maxn 都是 1e4 + 5 )。 对 f :sort 排序,unique 去重,如此,每个端点 index 就有了自己的 “指纹” 。 对每个询问,使用 lower_bound 寻找它的指纹,将它的指纹作为 l、r 进行并查集。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1e4 + 5 ;
int N, M;
int ans;
int par[ maxn] ;
int val[ maxn] ;
int f[ maxn] ; int cnt;
struct NODE{
int l, r, w;
NODE ( int l, int r, int w) : l ( l) , r ( r) , w ( w) { } ;
} ;
queue< NODE> Q;
void INIT ( ) {
ans = 0 ;
cnt = 0 ;
memset ( par , - 1 , sizeof ( par) ) ;
memset ( val , 0 , sizeof ( val) ) ;
return ;
}
int FIND ( int i) {
if ( par[ i] == - 1 )
return i;
int tp = par[ i] ;
par[ i] = FIND ( par[ i] ) ;
val[ i] = ( val[ i] + val[ tp] ) % 2 ;
return par[ i] ;
}
void UNION ( int w, int l, int r, int parl, int parr) {
par[ parr] = parl;
val[ parr] = ( val[ l] + w - val[ r] + 2 ) % 2 ;
return ;
}
int main ( ) {
ios: : sync_with_stdio ( false) ;
cin. tie ( 0 ) ;
while ( cin>> N>> M) {
INIT ( ) ;
for ( int i= 0 ; i< M; i++ ) {
int l, r, w;
string str;
cin>> l>> r>> str;
if ( str. size ( ) == 3 )
w = 1 ;
else
w = 0 ;
l-- ;
Q. push ( NODE ( l, r, w) ) ;
f[ cnt++ ] = l;
f[ cnt++ ] = r;
}
sort ( f , f+ cnt) ;
int n = unique ( f , f+ cnt) - f;
while ( Q. size ( ) ) {
NODE cur = Q. front ( ) ; Q. pop ( ) ;
if ( ans)
continue ;
int w = cur. w ;
int l = lower_bound ( f , f+ n , cur. l) - f;
int r = lower_bound ( f , f+ n , cur. r) - f;
int parl = FIND ( l) ;
int parr = FIND ( r) ;
if ( parl == parr)
if ( ( val[ l] + w) % 2 != val[ r] )
ans = M - Q. size ( ) - 1 ;
else
;
else
UNION ( w , l , r , parl , parr) ;
}
if ( ! ans)
ans = M;
cout<< ans<< endl;
}
return 0 ;
}