Subject to the effect
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是"1 X Y",表示X和Y是同类。
第二种说法是"2 X Y",表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。
Input
first line two integers N and K, separated by a space.
K The following three lines each is a positive integer D, X, Y, separated by a space between the two numbers, where D indicates the type of argument.
If D = 1, it indicates that X and Y are similar.
If D = 2, then X represents eat Y.
Output
is only one integer representing the number of lies.
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
Problem-solving ideas
This question is easy to want to simply argue, I just started to understand the wrong I have done in front of a question - gang, so I think this question is simple food chain of two tree - friends and enemies tree tree, so just I began to write code like this:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e3+7;
int f[maxn],a[maxn]; //上级数组,i当前的父亲节点
int n,k,d,x,y,num;
int findf(int x){ //查找朋友上级
return f[x]==x?x:f[x]=findf(f[x]);
}
int finda(int x){ //查找敌人上级
return a[x]==x?x:a[x]=finda(a[x]);
}
void add(int d,int x,int y){ //合并操作
if(d==1)
f[x]=y;
else if(d==2)
a[x]=y;
}
void Init(int n){ //初始化
for(int i=1;i<=n;i++){f[i]=i;a[i]=i;}
}
int main(){
cin>>n>>k;
Init(n);
num=0;
while(k--){
cin>>d>>x>>y;
if(x>n||y>n){
num+=1;
cout<<"-"<<endl;
continue;
}
else if(x==y&&d==2){
num+=1;
cout<<"--"<<endl;
continue;
}
int x1=findf(x);
int y1=findf(y);
int x2=finda(x);
int y2=finda(x);
if((d==1)&&x1!=y1&&x2==y2){
num+=1;
cout<<"---"<<endl;
continue;
}
else if((d==2)&&x2!=y2&&x1==y1){
num+=1;
cout<<"----"<<endl;
continue;
}
if(x1!=y1&&x2!=y2){
add(d,x,y);
}
}
cout<<num<<endl;
return 0;
}
The answer is wrong, I have found, can not regard him as a simple disjoint-set, you should find another idea to re-analyze the relationship between each node and the node.
What is the weighted disjoint-set?
Answer: When the investigation and sets a path compression and merge operations, these weights have certain attributes to their relationship with the parent node, change-rooted relationship with the host tree.
Relationship between a root node and each of his children nodes should be recorded, it is assumed:
a-> b 0 offset a and b grade
a-> b is offset a 1 b eaten
a-> b offset eat a 2 b
to create a structure. But the search for the relationship between multi-node will join relationship is complicated here by the knowledge vector analyze d under 1 and 2, the relationship of the root node = a and b of the root node:
- If b is equal to a root node of the root node: a and b are described in a tree, to determine the relationship between a and b, must know a-> root and root relationships -> b relationships (where direction of the problem not to confuse !!)
i.e., (X-> Y) .relation = (X-> RX) .relation + (the RX-> Y) .relition
= (. 3-Relation [X] Relation + [Y])% 3 - If a root node of the root node is not equal to b: a and b illustrate different trees, to determine the relationship between a and b, it is necessary to know the relationship a-> a root node and a root node -> b the root of the root node and b -> b of the relationship.
That is, rx-> ry = (relation [ x] + d-1 + 3-relation [y])% 3 = relation [ry]
In addition, this problem can only input and output scanf and printf, otherwise it will time out! ! !
Specific code as follows:
Code
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 50010
typedef long long ll;
struct node{
int num;
int relation;
}f[maxn];
int n,k,d,x,y,sum;
int find(int x){
int temp;
if(x==f[x].num) return x;
temp=f[x].num; //路径压缩
f[x].num=find(temp);
f[x].relation=(f[x].relation+f[temp].relation)%3; //关系域更新
return f[x].num; //根结点
}
void add(int x,int y,int d){
int f1=find(x);
int f2=find(y);
f[f2].num=f1; //合并树 注意:被 x 吃,所以以 x 的根为父
f[f2].relation=(f[x].relation-f[y].relation+3+(d-1))%3; //对应更新与父节点的关系
}
void Init(int n){ //初始化
for(int i=1;i<=n;i++){f[i].num=i;f[i].relation=0;}
}
int main(){
scanf("%d%d",&n,&k);
Init(n);
sum=0;
while(k--){
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n||(x==y&&d==2)){
sum+=1;
//cout<<"-"<<endl;
continue;
}
else if(find(x)==find(y)){
if((d==1)&&f[x].relation!=f[y].relation){ //如果x与y是同类,则说明两者根节点的关系是一样的
sum+=1;
//cout<<"---"<<endl;
continue;
}
else if((d==2)&&(3-f[x].relation+f[y].relation)%3!=d-1){//此时要满足x吃y,则必须满足x的根节点吃y,即f[y].relation=1,
sum+=1;
//cout<<"----"<<endl;
continue;
}
}
else
add(x,y,d);
}
printf("%d\n",sum);
return 0;
}