您的位置:首页 > 其它

poj 1733 并查集+偏移向…

2013-12-14 20:04 363 查看
题意: 题目给出一个有0、1组成的序列 , 长度为n 。 下面有m个条件 , 每个条件是:给出一个x到y的连续序列 ,
和这个序列中有偶数个1还是奇数个1 , 因为给出的条件可能有矛盾 , 所以要求出前多少个条件是没矛盾的。

这题有点意思 , 对于并查集的题目 , 首先要找到根节点 , 就是怎么来确定根节点 。

我们用:

0 : 表示偶数个1

1 : 表示奇数个1

我们用f[x-1] 表示0 到 x-1中1的个数是偶数还是奇数 , 如果 x 到 y有偶数个1 , 则 f[x-1]^f[y] =
0

反正有奇数个 , 则f[x-1]^f[y] = 1;

所以我们可以判断每个点和根的关系 , 来得到他们之间的关系 。

这题的偏移向量方程:

1、f[y] = abs(f[g]-f[h]+d); 
根节点的偏移方程 

2、f[x] = (f[x]+f[fa])%2;  子节点的偏移方程

代码:

#include

#include

#include

#include

using namespace std;

const int maxn = 50010*2;

int  p[maxn] , f[maxn];

int n , m;

int find(int x)

{

    if(p[x] ==
x)  return x;

    int fa =
p[x];

    p[x] =
find(fa);

    f[x] =
(f[x]+f[fa])%2;

    return
p[x];

}

int main()

{

   
maphash;

   
map::iterator it;

   
while(scanf("%d" , &n) != EOF)

    {

   
    

   
    scanf("%d" ,
&m);

   
    int i , j ,
x , y , k = 0;

   
    int g ,
h;

   
    char
cf[10];

   
    int bz =
-1;

   
    bool pre =
false;

   
    memset(f , 0
, sizeof(f));

   
    for(i = 0; i
<= 50010; i++)

   
  
   
 p[i] = i;

   
    for(i = 1; i
<= m; i++)

   
    {

   
  
   
 scanf("%d %d %s" , &x , &y , cf);

   
  
   
 if(pre)  continue;

   
  
   
 g = h = -1;

   
  
   
 it = hash.find(x-1);

   
  
   
 if(it != hash.end())

   
  
   
   
 g = it->second;

   
  
   
 else  hash[x-1] = k++ , g =
k-1;

   
  
   
 it = hash.find(y);

   
  
   
 if(it != hash.end())

   
  
   
   
 h = it->second;

   
  
   
 else  hash[y] = k++ , h =
k-1;

   
  
   
 x = find(g) , y = find(h);

   
  
   
 if(cf[0] == 'e')

   
  
   
 {

   
  
   
   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: