Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 54761 | Accepted: 16056 |
Description
Input
Output
Sample Input
100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5
Sample Output
3解题思路:
#include <iostream> #include <cstdio> using namespace std; const int MAX_N = 100000; //最大数量 int parent[MAX_N]; //父亲 int rank[MAX_N]; //树的高度 //并查集初始化 void init(int n){ for(int i = 0; i < n; ++i){ parent[i] = i; rank[i] = 0; } } //查找根节点 int find(int x){ if(parent[x] == x){ return x; } else { //递归查找至根节点,并将由该点到根节点上的所有节点的parent置为根节点 return parent[x] = find(parent[x]); } } //合并x和y所属集合 void unite(int x, int y){ x = find(x); y = find(y); if(x == y){ return; } if(rank[x] < rank[y]){ //x的高度小于y的,则以y为根节点 parent[x] = y; } else { parent[y] = x; if(rank[x] == rank[y]){ //如果高度相同,x的高度加一 rank[x]++; } } } //判断x和y是否为一个并查集 bool same(int x, int y){ return find(x) == find(y); } int N,K; //N只动物,K组数据 int T[MAX_N]; //信息类型 int X[MAX_N]; //X数组 int Y[MAX_N]; //Y数组 void solve(){ //解决函数 //初始化并查集 //这里的3N范围为A[0,N),B[N,2N),C[2N,3N) init(N * 3); int ans = 0; for(int i = 0; i < K; ++i){ int t = T[i]; int x = X[i] - 1; //范围变为[0,N-1] int y = Y[i] - 1; //范围变为[0,N-1] if(x < 0 || y < 0 || x >= N || y >= N){ ++ans; continue; } if(t == 1){ //x,y属于同一种类 //如果出现了x与y不是同一种类,也就是说x吃y,或者x被y吃的情况,则非法 if(same(x, (int)(y + N)) || same(x, y + 2 * N)){ ++ans; } else { //否则,将x,y归为同一种类,三个集合都归类 unite(x, y); unite(x + N, y + N); unite(x + 2 * N, y + 2 * N); } } else { //x吃y //如果出现了x与y是同一类或者y吃x的情况,则非法 if(same(x, y) || same(x, y + 2 * N)){ ++ans; continue; } else { //否则,将x,y的吃的关系,归为一类,三个集合都这样归类。这样,如果后续出现x,y同种类或者是y吃x,则非法 unite(x, y + N); unite(x + N, y + 2 * N); unite(x + 2 * N, y); } } } printf("%d\n",ans); } int main() { scanf("%d%d",&N,&K); for(int i = 0; i < K; i++){ scanf("%d%d%d",&T[i],&X[i],&Y[i]); } solve(); return 0; }