1 4 5
2017 UESTC Training for Data Structures
UESTC 1594 老司机的奇幻漂流
题意:三个东西构成一个食物链关系,A->B, B->C, C->A,给出m条关系,问是否有矛盾。
并查集 食物链
每个点有三个成员A、B、C,
当X和Y是同类时, _merge(X, Y), _merge(X+n, Y+n), _merge(X+2*n, Y+2*n);
当X攻击Y时, _merge(X+n, Y), _merge(X+2*n, Y+n), _merge(X, Y+2*n);
每次判断是否 if(x > n || x < 1 || y > n || y < 1){
ans.push_back(i);
continue;
}
然后插入前判断
如果是同类 if(_find(x+n) == _find(y) || _find(x) == _find(y+n)){
ans.push_back(i);
continue;
}
如果X攻击Y if(_find(x) == _find(y) || _find(x) == _find(y+n)){
ans.push_back(i);
continue;
}
复杂度 O(n)
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 5e4 + 8;
int father[3*MAXN], _rank[3*MAXN];
inline void DisjointSet(int n)
{
for(int i = 0; i <= 3*n; i++){
father[i] = i;
}
}
inline int _find(int v)
{
return father[v] = father[v] == v ? v : _find(father[v]);
}
inline void _merge(int x, int y)
{
int a = _find(x), b = _find(y); //
if(_rank[a] < _rank[b]){
father[a] = b;
}
else{
father[b] = a;
if(_rank[a] == _rank[b]){
_rank[a]++;
}
}
}
vector ans;
int main()
{
#ifdef LOCAL
freopen("l.txt", "r", stdin);
//freopen("l.out", "w", stdout);
int T = 4;
while(T--){
#endif // LOCAL
//ios::sync_with_stdio(false); cin.tie(0);
int n, m, t, x, y, i;
scanf("%d%d", &n, &m);
DisjointSet(n);
for(i = 1; i <= m; i++){
scanf("%d%d%d", &t, &x, &y);
if(x > n || x < 1 || y > n || y < 1){
ans.push_back(i);
continue;
}
if(t == 1){
if(_find(x+n) == _find(y) || _find(x) == _find(y+n)){
ans.push_back(i);
continue;
}
_merge(x, y);
_merge(x + n, y + n);
_merge(x + 2*n, y + 2*n);
}
else{
if(_find(x) == _find(y) || _find(x) == _find(y+n)){
ans.push_back(i);
continue;
}
_merge(x + n, y);
_merge(x + 2*n, y + n);
_merge(x, y + 2*n);
}
}
if(ans.empty()) printf("0");
else{
sort(ans.begin(), ans.end());
int sz = ans.size();
for(int i = 0; i < sz; i++){
if(i == 0) printf("%d", ans[i]);
else printf(" %d", ans[i]);
}
// putchar('\n');
}
#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}
Thank you!
------from ProLights