题意:
给出n个数字,m段话。
每段话 x,y ,op 表示从x到y有奇数 的个数为 奇数或偶数
判断前几句话是对的。
思路:
看了kuangbin大神的博客理解了好久,才看明白。mp是为了离散化,因为数字过长,然而输入却不长,因此每次mp操作都是为新插入的数字建立一个节点,如果有则不建立
find函数如普通带权并查集想法相同
总结:
做完此题才初步理解何种题型才可以作为带权并查集。必定最后如果合并都可以成为一个根 N个下一层的叶节点。如果不行则一定不是带权并查集,多为BFS 或者dfs
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <map>
using namespace std;
int F[6010];
int val[6010];
int find(int x)
{
if(F[x]==-1) return x;
int tmp=find(F[x]);
val[x]=val[x]^val[F[x]]; //下面类似的写成(val[x]+val[F[x]])%2也可以,一个意思
return F[x]=tmp;
}
int tol=0;
map <int ,int > mp;
int insert(int x)
{
if(mp.find(x)==mp.end()) mp[x]=tol++;
return mp[x];
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(F,-1,sizeof(F));
memset(val,0,sizeof(val));
int x,y;
tol=0;
mp.clear(); //千万别落下
char op[5];
int ans=m;
for(int i=0;i<m;i++)
{
scanf("%d%d%s",&x,&y,&op);
// if(x>y)
// swap(x,y); //少了不错
int u,v;
if(ans!=m)
continue;
u=insert(x-1);
v=insert(y);
int t1,t2;
t1=find(u);
t2=find(v);
int tmp;
if(op[0]=='e')
tmp=0;
else
tmp=1;
if(t1==t2)
{
if(val[u]^val[v]!=tmp)
ans=i;
}
else
{
F[t2]=t1;
val[t2]=val[u]^val[v]^tmp;
}
}
cout<<ans<<endl;
}
}