您的位置:首页 > 其它

POJ1182-食物链

2016-04-27 12:52 316 查看
该题有三种动物,我们可以把一个并查集分成三份:x,x+n, x+2n分别表示A,B,C三种动物。

当x与y是同类时,x与y可能是三种动物中的任意一种,则将(x, y)、(x+n, y+n)、(x+2n, y+2n)合并。

当x吃y时,x与y可能是三种捕食关系中的一种,x,y为异类,则合并A吃B(x, y+n)、B吃C(x+n, y+2n)、C吃A(x+2n, y)。

于是,当x,y处于同一个n内表示x,y为同类。

x,y跨过不同的n即表示x吃y。

对逐个语句进行分析时,先判断语句类型。

当语句表示x, y同类时,检查x,y是否为捕食关系。

当语句表示x吃y时,检查x,y是否是同类和x是否能够吃y。

#include <cstdio>

const int MAX_N = 5*10e3;
const int MAX_K = 10e5;

int par[3*MAX_N+5];
int rank[3*MAX_K+5];
int T[MAX_K];
int X[MAX_K];
int Y[MAX_K];

void init(int n)
{
for (int i = 0; i < n; i++) {
par[i] = i;
rank[i] = 0;
}
}

int find(int x)
{
if (par[x] == x) {
return x;
}
else {
return par[x] = find(par[x]);
}
}

void unite(int x, int y)
{
x = find(x);
y = find(y);
if (x == y) {
return;
}

if (rank[x] < rank[y]) {
par[x] = y;
}
else {
par[y] = x;
if (rank[x] == rank[y]) {
rank[x]++;
}
}
}

bool same(int x, int y)
{
return find(x) == find(y);
}

int main()
{
int n, k;
scanf("%d%d", &n, &k);

for (int i = 0; i < k; i++) {
scanf("%d%d%d", &T[i], &X[i], &Y[i]);
}

init(3 * n);

int ans = 0;
for (int i = 0; i < k; i++) {
int t = T[i];
int x = X[i] - 1;
int y = Y[i] - 1;

if (x < 0 || n <= x || y < 0 || n <= y) {
ans++;
continue;
}

if (t == 1) {
if (same(x, y + n) || same(x, y + 2 * n)) {
ans++;
}
else {
unite(x, y);
unite(x + n, y + n);
unite(x + 2 * n, y + 2 * n);
}
}
else {
if (same(x, y) || same(x, y + 2 * n)) {
ans++;
}
else {
unite(x, y + n);
unite(x + n, y + 2 * n);
unite(x + 2 * n, y);
}
}
}

printf("%d\n", ans);

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