vijos 1112 小胖的奇偶 并查集+哈希表
2010-07-17 11:27
856 查看
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
如何转化成并查集?
a b even等价于(0..a-1)与(0..b)同奇同偶
a b odd等价于(0..a-1)与(0..b)不同奇同偶
这样对于a b even,就union(same(a-1),same(b))&union(diff(a-1),diff(b))
对于a b odd,则union(same(a-1),diff(b))&union(diff(a-1),same(b))
same(x)和diff(x)随便选,比如same(x):=x;diff(x):=x+block;
反之,find(same(a-1))=find(same(b))等价于a b even(此时必然有find(diff(a-1))=find(diff(b))),find(diff(a-1))=find(same(b))等价于a b odd(同样此时必然有find(same(a-1))=find(diff(b)))这样就可以判断了.
循环每个提问,先判断,不符合就writeln&break,否则union;
但这样还不可以,因为n<=10^9,会MLE.
这就用着hash了.n很大,但m很小(<=5000),这样会出现的数<=10000个,所以只需要对这10000个数DisUnionJet,为了把这10000个数一一映射到0..10000中,我们用hash.function hash(x)是原来的x在hashtable中的位置,原来的x则映射在hashtable中.以后就可以用hash(x)代替x了.这里的hash方法叫做开放寻址法(参见算法导论)
当然,这样same(x):=same(hash(x));diff(x):=diff(hash(x))
另外再设一个bb:boolean来判断如果循环后i=n时有没有经历break;
这样,程序'应该'就完成了
程序有3个难点:(1)区间奇偶转化为两区间奇偶是否相同(还是比较简单的)(2)两区间奇偶是否相同转化成并查集模型(3)利用hash压缩空间.
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int BLOCK=10000;
const int HASHING=6000;//important
int fath[2*BLOCK+1],hash_table[HASHING+1];
int hash(int x)//构建哈希表
{
int ret;
ret=x%HASHING;
while(hash_table[ret]!=-1&&hash_table[ret]!=x) ret=(ret+1)%HASHING;
hash_table[ret]=x;
return ret;
}//important
int find(int x){return fath[x]==x?x:fath[x]=find(fath[x]);}
void uion(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return ;
fath[x]=y;
}
int main()
{
int len,n;
while(cin>>len>>n)
{
int ans,flag=0;
for(int i=1;i<2*BLOCK+1;i++) fath[i]=i;
memset(hash_table,-1,sizeof(hash_table));//初始化哈希表 important
for(int ci=1;ci<=n;ci++)
{
int a,b,signal;
string str;
cin>>a>>b>>str;
if(flag) continue;
signal=(str=="even"?1:0);//1表示偶数,0表示奇数
a=hash(a-1);//important
b=hash(b);//important
if(signal)
{
if(find(a)==find(b+BLOCK)) {ans=ci-1;flag=1;continue;}
uion(a,b);
uion(a+BLOCK,b+BLOCK);
}
else
{
if(find(a)==find(b)) {ans=ci-1;flag=1;continue; }
uion(a,b+BLOCK);
uion(a+BLOCK,b);
}
}
if(flag==0) ans=n;
cout<<ans<<endl;
}
return 0;
}
相关文章推荐
- vijos1112小胖的奇偶(并查集,区间转两端线段)
- Vijos P1110 小胖邮递员(HNOI2004)题解
- VijosP1112:小胖的奇偶
- 【vijos1144】小胖守皇宫(树形DP)
- vijos 小胖守皇宫
- parity - [vijos]小胖的奇偶
- 【动态规划】【最长公共子序列】Vijos P1111 小胖的水果
- vijos 1111 小胖的水果【lcs】
- 小胖守皇宫 vijos1144 树形dp
- Vijos 1144 小胖守皇宫
- Vijos P1111小胖的水果
- VIJOS-P1144 小胖守皇宫
- Vijos[1144]小胖守皇宫 树动规
- vijos1089——小胖抗日
- VIJOS-P1144 小胖守皇宫(树形dp)
- vijos 1110小胖邮递员;bzoj 1210: [HNOI2004]邮递员
- 【动态规划】【最长公共子序列】Vijos P1111 小胖的水果
- spfa——vijos1089小胖抗日
- Vijos 1144 小胖守皇宫 【树形DP】
- VIJOS P1144 小胖守皇宫