区间上的并查集,写过这类题的找到思路不难。
题目给的数的范围特别大,不得不离散化,这里采用map的方式来离散化。
具体解题思路可参考本博客hdu3038。
map离散化是指,比如1~10000,如果采用传统方式,明显是1和10000合并,但是离散化之后,用1代表1,2代表10000,1和2的合并便取代了1和10000的合并。采用map离散化,将原始值作为key,便能实现快速查找判断是否出现过。
代码:
#include <iostream>
#include <cstring>
#include <map>
#include <string>
using namespace std;
const int N=10005;
int father[N];
int rank[N];
map <int,int> m;
void init()
{
m.clear();
memset(rank,0,sizeof(rank));
for (int i=0;i<N;i++)
father[i]=i;
}
int find(int x)
{
if (x==father[x])
return x;
int t=father[x];
father[x]=find(father[x]);
rank[x]^=rank[t];
return father[x];
}
int Union(int a,int b,int k)
{
//cout<<a<<" "<<b<<endl;
int x=find(a);
int y=find(b);
//cout<<x<<" "<<y<<endl;
if (x==y)
{
if ((rank[a]^rank[b])!=k)
return 0;
else
return 1;
}
father[y]=x;
rank[y]=rank[b]^rank[a]^k;
//cout<<rank[y]<<endl;
return 1;
}
int main()
{
int n,k;
cin>>n>>k;
if (k==0)
cout<<0<<endl;
int a,b;
string s;
int cnt=0;
init();
for (int i=1;i<=k;i++)
{
cin>>a>>b>>s;
a--;
map <int,int>::iterator i1,i2;
i1=m.find(a);
if (i1==m.end())
{
m[a]=cnt;
cnt++;
}
i2=m.find(b);
if (i2==m.end())
{
m[b]=cnt;
cnt++;
}
int p;
if (s[0]=='e')
p=0;
else
p=1;
if (!Union(m[a],m[b],p))
{
cout<<i-1<<endl;
break;
}
else if (i==k)
cout<<k<<endl;
}
//system("pause");
return 0;
}