思路:
- 关于本文中首次用到的一些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;
}