食物链 并查集
食物链题目链接
刚开始看题目的时候,不知道如何维护谁吃谁的关系,只知道维护谁是谁的同类。
还是把知识点学得太死了,不知道变通。
下面还有大佬的题解方便复习不懂的知识点。
有两种做法:
- 并查集数组开三倍的空间
- 带权并查集
在这里安利一下ACwing y总的算法基础课和提高课讲的真得好
方法一
思路:将数组开3倍大,a表示自身的一层(即a类),a+n表示被a吃掉的一类,a+2n表示能吃a的一类。
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define INF 0x3f3f3f3f
#define PII pair<int, int>
#define rep(i, l, r) for (int i = l; i < r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define rep2(i, l, r) for (int i = l; i * i <= r; i++)
#define rep3(i, l, r) for (LL i = l; i * i * i <= r; i++)
#define Min(a, b) a > b ? b : a
#define Max(a, b) a > b ? a : b
#define endl '\n'
#define debug "-----"
using namespace std;
typedef long long LL;
const LL mod = 1e9;
const int N = 1e6 + 10, M = 10100;
LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
int p[N*2],sum;
int n,k;
int d,x,y;
int ans;
map<int,int>mp;
int find( int x ){
if( p[x] != x ) p[x] = find( p[x] );
return p[x];
}
void merge_( int x , int y ){
p[ find( x ) ] = find( y );
}
int main()
{
IOS;
cin >> n >> k;
rep( i , 1 , 3*(n+1) ) p[i] = i;
while( k-- ){
cin >> d >> x >> y;
if( x > n || y > n ){ ans++; continue; }
if( d == 1 ){
if( find(x) == find(y+n) || find(x) == find(y+2*n) ) { ans++; 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+2*n) ) { ans++;continue; }
merge_( x , y+n );
merge_( x+n , y+2*n );
merge_( x+2*n , y );
}
}
cout << ans;
return 0;
}
方法二
思路:不断得维护昕的结点到父亲结点的距离,并根据距离%3后的大小来判断与两个点是什么关系。
1. 距离之差为0时表明是同类。
2. 距离之差为1时表明是不是关系。
d[x]数组维护的是该点X到他的父亲结点p[X]的距离
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define INF 0x3f3f3f3f
#define PII pair<int, int>
#define rep(i, l, r) for (int i = l; i < r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define rep2(i, l, r) for (int i = l; i * i <= r; i++)
#define rep3(i, l, r) for (LL i = l; i * i * i <= r; i++)
#define Min(a, b) a > b ? b : a
#define Max(a, b) a > b ? a : b
#define endl '\n'
#define debug "-----"
using namespace std;
typedef long long LL;
const LL mod = 1e9;
const int N = 1e6 + 10, M = 10100;
LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
int p[N],d[N];
int n,k;
int x,y,d1;
int ans;
int find( int x ){
if( p[x] != x ){
int t = find(p[x]);
d[x] += d[p[x]];
p[x] = t;
}
return p[x];
}
int main()
{
IOS;
cin >> n >> k;
rep( i , 1 , n+1 ) p[i] = i;
while( k-- ){
cin >> d1 >> x >> y;
if( x > n || y > n ){ ans++; continue; }
int px = find(x) , py = find(y);
if( d1 == 1 ){
if( px == py && (d[x]-d[y])%3 != 0 ) ans++;
else if( px != py ) {
p[px] = py;
d[px] = d[y]-d[x];
}
}
else{
if( px == py && (d[x]-d[y]-1)%3 != 0 ) ans++;
else if( px != py ) {
p[px] = py;
d[px] = d[y]+1-d[x];
}
}
}
cout << ans;
return 0;
}