Private training winter - disjoint-set B - food chain

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:

  1. 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
  2. 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;
}

Published 26 original articles · won praise 0 · Views 569

Guess you like

Origin blog.csdn.net/atnanajiang/article/details/104102949