您的位置:首页 > 其它

POJ 1182 解题报告

2014-11-20 04:30 288 查看
这道题似乎是union-find的经典题目。

这道题我在捕食关系上面弄得很乱,(改改说不定能弄对),最后看了discuss上面一个同学的解法写的,最后和这个同学的代码就一模一样了:http://poj.org/showmessage?message_id=344806

大致理解为:对任意一个编号为i的动物,它能捕食的动物集合和N+i都是一个集合的, 捕食它的动物集合和2N+i是一个集合的。这样总的集合大小为3N,编号为0~3N-1。好处是理解比较清晰。

判断两个动物(X, Y)可不可能是同一个类型的,只需要比较下Y和X捕食的动物或捕食X的动物在不在一个集合里面就可以了。如果可能是一个类型的,那就是真话,把X,Y放到一个集合里面,同时, X+N和Y+N,以及X+2N和Y+2N也要并起来。

判断两个动物(X,Y)是不是X能够捕食Y,也比较清晰。即看Y是不是和X或者捕食X的动物在一个集合里面。如果不能的话,那么X是可能会捕食Y的。这样,把X和捕食Y的放在一个集合里面。同理,把捕食X的和Y捕食的并起来,把X捕食的和Y并起来。

1182Accepted1796K297MSG++2178B
/*
ID: thestor1
LANG: C++
TASK: poj1182
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>

using namespace std;

int findset(int X, std::vector<int> &parent)
{
if (parent[X] != X)
{
parent[X] = findset(parent[X], parent);
}
return parent[X];
}

void unionset(int X, int Y, std::vector<int> &parent, std::vector<int> &rank)
{
int rx = findset(X, parent);
int ry = findset(Y, parent);
if (rx == ry)
{
return;
}
if (rank[rx] < rank[ry])
{
parent[rx] = ry;
}
else if (rank[ry] < rank[rx])
{
parent[ry] = rx;
}
else
{
parent[rx] = ry;
rank[ry]++;
}
}

int main()
{
// std::ios::sync_with_stdio(false);
int N, K;
// cin >> N >> K;
scanf("%d%d", &N, &K);

std::vector<int> parent(3 * N);
std::vector<int> rank(3 * N);
for (int i = 0; i < 3 * N; ++i)
{
parent[i] = i;
rank[i] = 0;
}

int nlies = 0;
for (int i = 0; i < K; ++i)
{
int D, X, Y;
// cin >> D >> X >> Y;
scanf("%d%d%d", &D, &X, &Y);

if (X < 1 || Y < 1 || X > N || Y > N)
{
nlies++;
continue;
}

if (X == Y)
{
if (D == 2)
{
nlies++;
}
continue;
}

X--, Y--;

// int rx = findset(X, parent);
int ry = findset(Y, parent);
// X and Y are the same group
if (D == 1)
{
if (findset(X + N, parent) == ry || findset(X + 2 * N, parent) == ry)
{
nlies++;
}
else
{
unionset(X, Y, parent, rank);
unionset(X + N, Y + N, parent, rank);
unionset(X + 2 * N, Y + 2 * N, parent, rank);
}
}
else
{
// X eats Y
assert (D == 2);
if (findset(X, parent) == ry || findset(X + 2 * N, parent) == ry)
{
nlies++;
}
else
{
unionset(X, Y + 2 * N, parent, rank);
unionset(X + N, Y, parent, rank);
unionset(X + 2 * N, Y + N, parent, rank);
}
}
}

// cout << nlies << endl;
printf("%d\n", nlies);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: