P2024 food chain (the kind of disjoint-set)

P2024 [NOI2001] food chain

Title Description

There are three types of animals in the animal kingdom A, B, C, three types of animal food chain constitute an interesting ring. A food B, B eat C, C eat A.
Animals prior N, 1 - id N. Each animal is A, B, C in kind, but we do not know it in the end is what kind of.
Some people describe this relationship N animal food chain formed by two different ways:

  • The first argument is "1 XY", represents the X and Y are similar.
  • The second argument is "2 XY", X represents eat Y.

This person for N animals, with the above two statements, one sentence by sentence to say K, K this sentence some true, some false. When one of the following three words, this sentence is a lie, the truth is otherwise.

  • If some of the current and previous conflicts true, then, is a lie
  • If the current X or Y greater than N, that lies
  • Current eat as saying X X, is a lie

Your task is given according to the total number of N and K words, the output of lies.

Input Format

The first line of two integers, N, K, N expressed animal, K words.
The second line of each line word

Output Format

Line, an integer representing the total number of lies.


The classic kind of disjoint-set to use

Seems to have called Weighted disjoint-set
thus feel disjoint-set is not a simple thing

We can and check the focus of each element, recording a \ (relation (x) \) , represents \ (x \) and \ (fa (x) \) relationship
\ (relation (x) \) there are three values :

  • 0 indicates \ (x \) and \ (fa (x) \) is the same
  • 1, it indicates \ (X \) is \ (fa (x) \) eaten
  • 2 shows \ (X \) eaten \ (fa (x) \)

Of course, the beginning of time each node of his own father, \ (in the Relation \) is 0, himself and his kind are

So, we are carrying path when compressed, updated \ (fa (x) \) at the same time, you have to update \ (relation (x) \)
consider that we know \ (relation (x), relation (fa (x )) \) , how to exit \ () x \ and its relationship Grandpa's?
Namely: \ ((in the Relation (the X-) + in the Relation (FA (the X-))) \ BMOD 3 \)
try to know, which are established for each case, because the lazy do not write out
in fact explains , three values are not just random taken, to the above simple formula to determine the significance of these three values according to how to write

Then consider another thing, \ (relation (x) \) is \ (x \) relative to its parent's information, then how \ (relation (x) \) to get it to its father with the information?
Try to know the three cases, a \ ((3-relation (x
)) \ bmod 3 \) slightly example, such as \ (X \) can eat \ (FA (X) \) , i.e. \ (relation (x) = 2 \
) then \ (. 3-Relation (X) =. 1 \) , which denotes that, \ (FA (X) \) is \ (X \) eaten

With this, it is possible to consider how to merge the two sets
set \ (x, y \) roots are \ (a find_xx, Findy \) , then we let \ (fa (findy) = findx
\) then \ (fa (findy) \) is updated, then \ (relation (findy) \) will also update
put the code against the code says should be relatively easy

inline void link(int x,int y,int findx,int findy,int o){
	fa[findy]=findx;
	relation[findy]=(3-relation[y]+o-1+relation[x])%3;
}

That ois the type of sentence, \ (O =. 1 \) represents the same kind, \ (O = 2 \) represents \ (X \) eat \ (Y \)
and even after this one word is completed, regardless of other nodes are omitted

To know \ (findx \) and (findy \) \ relationship, certainly from \ (x, y \) to start, because there is no relationship between other nodes connected edges is uncertain
\ (o-1 \) , namely \ (y \) with respect to the relative \ (x \) relationship, in other words, if \ (y \) father \ (x \) , so \ (relation (y) = o-1 \)
then we can imagine the original tree some edge, that is, in the figure below blue edges that are directed by the father son

Said before binding requirements \ (x \) with respect to the method of its relationship Grandpa, we can give this method coupled with deeper
is seeking \ (findy \) relationship with respect to its father's father's father's (((
In fact, those that follow the blue arrows to go back, then gone so three, went to the \ (findx \) the
then three segment generated blue arrow \ (relation \) values add up to 3 die on the line
this also reflects determined in a clever way \ (relation \) how important value, if it is determined blind, there is no simple formula, then the two-step Fortunately, this step becomes extremely cumbersome to three
so that \ ((. 3-Relation (Y)) + (. 1-O) + Relation (X) \ BMOD. 3 \) , order is counter to the direction of the arrow

So this question basically clear, some details look at the code just fine
, but there is a place on the realization to talk about, is the findfunction

int find(int x){
	if(fa[x]==x) return x;
	int tmp=fa[x];
	fa[x]=find(fa[x]);
	relation[x]=(relation[x]+relation[tmp])%3;
	return fa[x];
}

Why is the first fa[x]=find(fa[x])after the update relation[x]?
Because the process fa[x]before, if it is used relation[fa[x]]to update relation[x], then the time fa[x]relationship with the roots may not be updated error message and can not be used to updaterelation[x]

Why should the definition of a tmp=fa[x]?
Because fa[x]=find(fa[x]), the fa[x]values have changed

So, check and set this thing in itself does not seem difficult, but some of the more advanced applications still have something of
the reasons of course, I was too konjac

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
	int x=0,y=1;
	char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
int n,m;
int fa[50006],relation[50006];
inline void link(int x,int y,int findx,int findy,int o){
	fa[findy]=findx;
	relation[findy]=(3-relation[y]+o-1+relation[x])%3;
}
int find(int x){
	if(fa[x]==x) return x;
	int tmp=fa[x];
	fa[x]=find(fa[x]);
	relation[x]=(relation[x]+relation[tmp])%3;
	return fa[x];
}
int main(){
	n=read();m=read();
	reg int ans=0;
	for(reg int i=1;i<=n;i++) fa[i]=i;
	for(reg int i=1,o,x,y;i<=m;i++){
		o=read();x=read();y=read();
		if(x>n||y>n){ans++;continue;}
		if(o==2&&x==y){ans++;continue;}
		int findx=find(x),findy=find(y);
		if(findx!=findy) link(x,y,findx,findy,o);
		else{
			if(o==1){if(relation[x]!=relation[y]) ans++;}
			else{
				if((relation[y]+3-relation[x])%3!=1) ans++;
			}
		}
	}
	std::printf("%d",ans);
	return 0;
}

Guess you like

Origin www.cnblogs.com/suxxsfe/p/12595969.html