AcWing 240. Combination of basic data structure of food chain

Title description

There are three types of animals in the animal kingdom, A, B, and C. The food chain of these three types of animals forms an interesting ring.

A eats B, B eats C, and C eats A.

There are currently N animals, numbered from 1 to N.

Each animal is one of A, B, and C, but we don't know which one it is.

Some people describe the food chain relationship formed by these N animals in two ways:

The first statement is "1 XY", which means X and Y are of the same kind.

The second statement is "2 XY", which means X eats Y.

This person uses the above two statements to say K sentences to N animals one after another. Some of these K sentences are true and some are false.

When a sentence satisfies one of the following three items, the sentence is false, otherwise it is true.

1) The current words conflict with some of the previous true words, which is a lie;
2) The current words X or Y is greater than N, which is a lie;
3) The current words mean that X eats X, which is a lie.

Your task is to output the total number of lies based on the given N and K sentences.

Input format The
first line is two integers N and K, separated by a space.

Each of the following K lines contains three positive integers D, X, Y, separated by a space between the two numbers, where D represents the type of argument.

If D=1, it means that X and Y are of the same kind.

If D=2, it means X eats Y.

The output format
has only one integer, which represents the number of lies.

Data range
1≤N≤50000,
0≤K≤100000
Input example:

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

Topic analysis

First, check the input and ask for k lines, explaining the relationship between two animals x and y each time.
Second, check how a sentence can be a lie

① In the current words, X or Y is greater than N, which is a lie. This is the easiest to judge, just need it if(x>n || y>n) ans++;.
② The current words conflict with the previous truth or the appearance of x eating x is a lie. In fact, the presence of x eating x is a conflict with the truth.
Therefore, we can put all the animals that can determine the correct relationship in a set. At the beginning, we only know that each animal does not eat itself, so each animal forms a set.
Secondly, in a set, we need to maintain the distance from the current node to the root node of the set d[i]. Because there are only three kinds of animals, the category of each animal can be used to kind[i] = d[i]%3represent the state relationship of the animals in a certain set. Kind = 1 0,2 1,0 eat eat eat 2, so when kind[i]%3 == kind[j]%3when i and j are the same species, kind[i]%3 == kind[j]%3when i eat represents the j.

Since it is the merging and querying of collections, of course the union search collection is used, but only a distance parameter needs to be maintained.

When the two species in the question asked are not in the same set, it means that the relationship between the two animals is undecided. The current word is the truth and there is no conflict. The two sets are merged according to the current word.
Update about distance

if(x和y同类)
	(d[sy]+d[y])%3 = d[x]%3
	即d[sy] = (d[x]%3+d[y]%3+3)%3
if(x吃y)
	d[x]%3 = (d[sy] +d[y]+1)%3 
	d[sy] = (d[x]%3-d[y]%3-1+3)
	 

When the two species in question are in the same collection, they may conflict with the truth.

非冲突状态
	同类:d[x] %3 == d[y]%3
	x吃y: d[x]%3 == (d[y]+1)%3

C++ code implementation

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 5e4+10;
int n, k;
int p[N], d[N];//p是并查集的集合,d[i]是i到根节点的距离

//带有路径压缩的并查集查找
int find(int x) {
    
    
    if(x != p[x]) {
    
    
        int t = p[x];
        p[x] = find(p[x]);
        d[x] += d[t];//将整个路径的距离加在一起就是当前节点到根节点的距离
    }
    return p[x];
}

int main() {
    
    
    cin>>n>>k;
    //初始化集合
    for(int i = 1; i < n; ++i) {
    
    
        p[i] = i;
    }
    int ans= 0;
    while(k--) {
    
    
        int D, x, y;
        scanf("%d%d%d", &D, &x, &y);
        if(x > n || y > n) {
    
    
            ans++;
            continue;
        }
        int sx = find(x);
        int sy = find(y);
        //只有在同一个集合才有可能冲突
        if(sx == sy) {
    
    
            //int dif = (d[x]%3 - d[y]%3 + 3)%3;
            if(D == 1) {
    
    
                if(d[x]%3 != d[y]%3) {
    
    
                    ans++;
                }
            }
            else {
    
    
                if(d[x]%3!= (d[y]+1)%3) {
    
    
                    ans++;
                }
            }
        }
        else{
    
    //不会冲突,合并两个集合
            p[sy] = sx;
            //1-->0, 2-->1, 3-->2
            //(d[y]+d[sy])%3 = d[x]%3
            //d[sy] = d[x]-d[y];
            if(D == 1) {
    
    
                d[sy] = (d[x]%3-d[y]%3+3)%3;
            }
            else{
    
    
                //(d[y]+d[sy])%3-d[x]%3 = 1
                d[sy] = (d[x]%3-d[y]%3-1+3)%3;
            }        
        }
    }
    cout<<ans<<endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/mwl000000/article/details/108531903