http://poj.org/problem?id=1182
开三种情况
1-n表示同类
1+n-n+n表示吃谁
2n+1-3n表示被谁吃
d=1
只需要判断
1、b和吃c的
2、b和被c吃的
看他们若同属一并查集就为假
此时需要合并的是
1、吃b的和吃c的
2、被b吃的和被c吃的
3、c和b
d=2
只需要判断
1、c和b吃的
2、c和b
此时需要合并的是
1、b和吃c的
2、被b吃的和c
3、吃b的和c吃的
#include<cstdio>
using namespace std;
const int maxn = 5e4 + 5;
int n, k;
int a, b, c;
int ans = 0;
int aaa1, bbb1, aaa2, bbb2, aaa3, bbb3; // 分别对应的三个祖先
int fa[150005]; // 三倍大的数组
inline int find(int t) // 标准找爸爸操作
{
if(fa[t] == t) return t;
return fa[t] = find(fa[t]);
}
inline void workk_same()
{
aaa1 = find(b);
bbb1 = find(c);
aaa2 = find(b + n);
bbb2 = find(c + n);
aaa3 = find(b + 2 * n);
bbb3 = find(c + 2 * n);
// 直接找出三个老祖宗
if(aaa1 == bbb2 || aaa1 == bbb3)
{
ans++;
return;
}
// 判定有没有符合要求
fa[aaa1] = bbb1;
fa[aaa2] = bbb2;
fa[aaa3] = bbb3;
// 合并
}
inline void workk_b_eat_c()
{
if(b == c)
{
ans++;
return;
}//下面表示b吃c;
aaa1 = find(b);
bbb1 = find(c);//同类
aaa2 = find(b + n);
bbb2 = find(c + n);//吃谁
aaa3 = find(b + 2 * n);
bbb3 = find(c + 2 * n);//被谁吃
if(aaa1 == bbb1 || aaa1 == bbb2 || aaa2 == bbb3 || aaa2 == bbb2 || aaa3 == bbb3 || aaa3 == bbb1)
{//几种
ans++;
return;
} // 判定是否合理
fa[aaa1] = bbb3;
fa[aaa2] = bbb1;
fa[aaa3] = bbb2; // 合并
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= 3*n; ++i)
fa[i] = i;
for(int i = 1; i <= k; ++i)
{
scanf("%d%d%d", &a, &b, &c);
if(b > n || c > n)
{
ans++;
continue;
}
if(a == 1) workk_same();
else workk_b_eat_c();
}
printf("%d", ans);
return 0;
}
也可以优化为
#include<cstdio>
using namespace std;
const int maxn = 5e4 + 5;
int n, k;
int a, b, c;
int ans = 0;
int aaa1, bbb1, aaa2, bbb2, aaa3, bbb3; // 分别对应的三个祖先
int fa[150005]; // 三倍大的数组
inline int find(int t) // 标准找爸爸操作
{
if(fa[t] == t) return t;
return fa[t] = find(fa[t]);
}
inline void workk_same()
{
aaa1 = find(b);
bbb1 = find(c);
aaa2 = find(b + n);
bbb2 = find(c + n);
aaa3 = find(b + 2 * n);
bbb3 = find(c + 2 * n);
// 直接找出三个老祖宗
if(aaa1 == bbb2 || aaa1 == bbb3)
{
ans++;
return;
}
// 判定有没有符合要求
fa[aaa1] = bbb1;
fa[aaa2] = bbb2;
fa[aaa3] = bbb3;
// 合并
}
inline void workk_b_eat_c()
{
if(b == c)
{
ans++;
return;
}//表示b吃;
aaa1 = find(b);
bbb1 = find(c);//同类
aaa2 = find(b + n);
bbb2 = find(c + n);//吃谁
aaa3 = find(b + 2 * n);
bbb3 = find(c + 2 * n);//被谁吃
if(aaa1 == bbb1 || aaa1 == bbb2 )
{//如果bc是同类、
ans++;
return;
} // 判定是否合理
fa[aaa1] = bbb3;
fa[aaa2] = bbb1;
fa[aaa3] = bbb2; // 合并
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= 3*n; ++i)
fa[i] = i;
for(int i = 1; i <= k; ++i)
{
scanf("%d%d%d", &a, &b, &c);
if(b > n || c > n)
{
ans++;
continue;
}
if(a == 1) workk_same();
else workk_b_eat_c();
}
printf("%d", ans);
return 0; // 程序再见!
}